This is the mail archive of the binutils@sourceware.org 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]
Other format: [Raw text]

Automatic embed of spu executables


This patch teaches a ppu linker to automatically handle embedding of
spu executables.  It does so by invoking the "embedspu" script on
finding an spu executable as one of its input files.

	* Makefile.am: Add dependency on ldemul-list.h for powerpc and
	spu target emul files.
	* configure.in: Check for mkstemp and waitpid.
	* Makefile.in: Regenerate.
	* configure: Regenerate.
	* config.in: Regenerate.
	* ldlang.c (input_file_chain): Make global.
	(lang_add_input_file): Don't set lang_has_input_file here.
	* ldlang.h (input_file_chain): Declare.
	* emultempl/ppc32elf.em (ppc_recognized_file): New function.
	(LDEMUL_RECOGNIZED_FILE): Define.
	* emultempl/ppc64elf.em (ppc64_recognized_file): New function.
	(LDEMUL_RECOGNIZED_FILE): Define.
	* emultempl/spuelf.em (struct tflist): New.
	(tmp_file_list): New var.
	(clean_tmp, embedded_spu_file): New functions.

Index: ld/Makefile.am
===================================================================
RCS file: /cvs/src/src/ld/Makefile.am,v
retrieving revision 1.234
diff -u -p -r1.234 Makefile.am
--- ld/Makefile.am	15 Mar 2007 14:17:19 -0000	1.234
+++ ld/Makefile.am	26 Mar 2007 03:41:46 -0000
@@ -722,6 +722,7 @@ eelf32_sparc_vxworks.c: $(srcdir)/emulpa
 	${GENSCRIPTS} elf32_sparc_vxworks "$(tdir_elf32_sparc_vxworks)"
 eelf32_spu.c: $(srcdir)/emulparams/elf32_spu.sh $(srcdir)/emultempl/spuelf.em \
   $(srcdir)/emultempl/spu_ovl.o \
+  ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32_spu "$(tdir_elf32_spu)"
 $(srcdir)/emultempl/spu_ovl.o: @MAINT@ $(srcdir)/emultempl/spu_ovl.S
@@ -819,21 +820,25 @@ eelf32mt.c: $(srcdir)/emulparams/elf32mt
 eelf32lppc.c: $(srcdir)/emulparams/elf32lppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emultempl/ppc32elf.em \
+  ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32lppc "$(tdir_elf32lppc)"
 eelf32lppcnto.c: $(srcdir)/emulparams/elf32lppcnto.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emultempl/ppc32elf.em $(ELF_DEPS) \
+  ldemul-list.h \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32lppcnto "$(tdir_elf32lppcnto)"
 eelf32lppcsim.c: $(srcdir)/emulparams/elf32lppcsim.sh \
   $(srcdir)/emulparams/elf32lppc.sh $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh $(srcdir)/emultempl/ppc32elf.em \
+  ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32lppcsim "$(tdir_elf32lppcsim)"
 eelf32ppcnto.c: $(srcdir)/emulparams/elf32ppcnto.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emultempl/ppc32elf.em $(ELF_DEPS) \
+  ldemul-list.h \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32ppcnto "$(tdir_elf32ppcnto)"
 eelf32ppcwindiss.c: $(srcdir)/emulparams/elf32ppcwindiss.sh \
@@ -854,28 +859,34 @@ eelf32openrisc.c: $(srcdir)/emulparams/e
 	${GENSCRIPTS} elf32openrisc "$(tdir_openrisc)"
 eelf32ppc.c: $(srcdir)/emulparams/elf32ppc.sh \
   $(srcdir)/emulparams/elf32ppccommon.sh $(srcdir)/emultempl/ppc32elf.em \
+  ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32ppc "$(tdir_elf32ppc)"
 eelf32ppc_fbsd.c: $(srcdir)/emulparams/elf32ppc_fbsd.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emultempl/ppc32elf.em $(ELF_DEPS) \
+  ldemul-list.h \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32ppc_fbsd "$(tdir_elf32ppc_fbsd)"
 eelf32ppcsim.c: $(srcdir)/emulparams/elf32ppcsim.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emultempl/ppc32elf.em $(ELF_DEPS) \
+  ldemul-list.h \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32ppcsim "$(tdir_elf32ppcsim)"
 eelf32ppclinux.c: $(srcdir)/emulparams/elf32ppclinux.sh \
   $(srcdir)/emulparams/elf32ppc.sh $(srcdir)/emulparams/elf32ppccommon.sh \
   $(srcdir)/emultempl/ppc32elf.em $(ELF_DEPS) \
+  ldemul-list.h \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf32ppclinux "$(tdir_elf32ppclinux)"
 eelf64ppc.c: $(srcdir)/emulparams/elf64ppc.sh $(srcdir)/emultempl/ppc64elf.em \
+  ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf64ppc "$(tdir_elf64ppc)"
 eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \
   $(srcdir)/emulparams/elf64ppc.sh $(srcdir)/emultempl/ppc64elf.em \
+  ldemul-list.h \
   $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} elf64lppc "$(tdir_elf64lppc)"
 eelf32i370.c: $(srcdir)/emulparams/elf32i370.sh \
Index: ld/configure.in
===================================================================
RCS file: /cvs/src/src/ld/configure.in,v
retrieving revision 1.46
diff -u -p -r1.46 configure.in
--- ld/configure.in	15 Mar 2007 14:17:20 -0000	1.46
+++ ld/configure.in	26 Mar 2007 03:41:51 -0000
@@ -102,7 +102,7 @@ AC_SUBST(HOSTING_LIBS)
 AC_SUBST(NATIVE_LIB_DIRS)
 
 AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h elf-hints.h limits.h sys/param.h)
-AC_CHECK_FUNCS(sbrk realpath glob)
+AC_CHECK_FUNCS(glob mkstemp realpath sbrk waitpid)
 AC_HEADER_DIRENT
 
 AC_MSG_CHECKING(for a known getopt prototype in unistd.h)
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.254
diff -u -p -r1.254 ldlang.c
--- ld/ldlang.c	24 Mar 2007 06:49:02 -0000	1.254
+++ ld/ldlang.c	26 Mar 2007 03:41:55 -0000
@@ -52,7 +52,6 @@ static struct obstack map_obstack;
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 static const char *startup_file;
-static lang_statement_list_type input_file_chain;
 static bfd_boolean placed_commons = FALSE;
 static bfd_boolean stripped_excluded_sections = FALSE;
 static lang_output_section_statement_type *default_common_section;
@@ -89,6 +88,7 @@ lang_output_section_statement_type *abs_
 lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type file_chain = { NULL, NULL };
+lang_statement_list_type input_file_chain;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 static const char *entry_symbol_default = "start";
 const char *entry_section = ".text";
@@ -988,7 +988,6 @@ lang_add_input_file (const char *name,
 		     lang_input_file_enum_type file_type,
 		     const char *target)
 {
-  lang_has_input_file = TRUE;
   return new_afile (name, file_type, target, TRUE);
 }
 
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.71
diff -u -p -r1.71 ldlang.h
--- ld/ldlang.h	21 Feb 2007 16:43:50 -0000	1.71
+++ ld/ldlang.h	26 Mar 2007 03:41:55 -0000
@@ -456,6 +456,7 @@ extern struct bfd_sym_chain entry_symbol
 extern const char *entry_section;
 extern bfd_boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
+extern lang_statement_list_type input_file_chain;
 
 extern int lang_statement_iteration;
 
Index: ld/emultempl/ppc32elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc32elf.em,v
retrieving revision 1.11
diff -u -p -r1.11 ppc32elf.em
--- ld/emultempl/ppc32elf.em	8 Dec 2005 11:41:12 -0000	1.11
+++ ld/emultempl/ppc32elf.em	26 Mar 2007 03:41:56 -0000
@@ -124,6 +124,25 @@ ppc_before_allocation (void)
 
 EOF
 
+if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
+  cat >>e${EMULATION_NAME}.c <<EOF
+/* Special handling for embedded SPU executables.  */
+extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
+static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *);
+
+static bfd_boolean
+ppc_recognized_file (lang_input_statement_type *entry)
+{
+  if (embedded_spu_file (entry, "-m32"))
+    return TRUE;
+
+  return gld${EMULATION_NAME}_load_symbols (entry);
+}
+
+EOF
+LDEMUL_RECOGNIZED_FILE=ppc_recognized_file
+fi
+
 # Define some shell vars to insert bits of code into the standard elf
 # parse_args and list_options functions.
 #
Index: ld/emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.51
diff -u -p -r1.51 ppc64elf.em
--- ld/emultempl/ppc64elf.em	13 Feb 2007 01:53:03 -0000	1.51
+++ ld/emultempl/ppc64elf.em	26 Mar 2007 03:41:56 -0000
@@ -459,6 +459,24 @@ ppc_lang_for_each_input_file (void (*fun
 
 EOF
 
+if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
+  cat >>e${EMULATION_NAME}.c <<EOF
+/* Special handling for embedded SPU executables.  */
+extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
+static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *);
+
+static bfd_boolean
+ppc64_recognized_file (lang_input_statement_type *entry)
+{
+  if (embedded_spu_file (entry, "-m64"))
+    return TRUE;
+
+  return gld${EMULATION_NAME}_load_symbols (entry);
+}
+EOF
+LDEMUL_RECOGNIZED_FILE=ppc64_recognized_file
+fi
+
 # Define some shell vars to insert bits of code into the standard elf
 # parse_args and list_options functions.
 #
Index: ld/emultempl/spuelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/spuelf.em,v
retrieving revision 1.3
diff -u -p -r1.3 spuelf.em
--- ld/emultempl/spuelf.em	27 Feb 2007 08:33:25 -0000	1.3
+++ ld/emultempl/spuelf.em	26 Mar 2007 03:41:56 -0000
@@ -238,6 +238,155 @@ gld${EMULATION_NAME}_finish (void)
 
 EOF
 
+if grep -q 'ld_elf.*ppc.*_emulation' ldemul-list.h; then
+  cat >>e${EMULATION_NAME}.c <<EOF
+#include "filenames.h"
+#include <fcntl.h>
+#include <sys/wait.h>
+
+struct tflist {
+  struct tflist *next;
+  char name[9];
+};
+
+static struct tflist *tmp_file_list;
+
+static void clean_tmp (void)
+{
+  for (; tmp_file_list != NULL; tmp_file_list = tmp_file_list->next)
+    unlink (tmp_file_list->name);
+}
+
+/* This function is called when building a ppc32 or ppc64 executable
+   to handle embedded spu images.  */
+extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
+
+bfd_boolean
+embedded_spu_file (lang_input_statement_type *entry, const char *flags)
+{
+  const char *cmd[6];
+  const char *sym;
+  char *handle, *p;
+  struct tflist *tf;
+  char *oname;
+  int fd;
+  pid_t pid;
+  int status;
+  union lang_statement_union **old_stat_tail;
+  union lang_statement_union **old_file_tail;
+  union lang_statement_union *new_ent;
+
+  if (entry->the_bfd->format != bfd_object
+      || strcmp (entry->the_bfd->xvec->name, "elf32-spu") != 0
+      || (entry->the_bfd->tdata.elf_obj_data->elf_header->e_type != ET_EXEC
+	  && entry->the_bfd->tdata.elf_obj_data->elf_header->e_type != ET_DYN))
+    return FALSE;
+
+  /* Use the filename as the symbol marking the program handle struct.  */
+  sym = strrchr (entry->the_bfd->filename, '/');
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  {
+    char *bslash = strrchr (entry->the_bfd->filename, '\\');
+
+    if (sym == NULL || (bslash != NULL && bslash > sym))
+      sym = bslash;
+    if (sym == NULL
+	&& entry->the_bfd->filename[0] != '\0'
+	&& entry->the_bfd->filename[1] == ':')
+      sym = entry->the_bfd->filename + 1;
+  }
+#endif
+  if (sym == NULL)
+    sym = entry->the_bfd->filename;
+  else
+    ++sym;
+
+  handle = xstrdup (sym);
+  for (p = handle; *p; ++p)
+    if (!(ISALNUM (*p) || *p == '$' || *p == '.'))
+      *p = '_';
+
+  if (tmp_file_list == NULL)
+    atexit (clean_tmp);
+  tf = xmalloc (sizeof (*tf));
+  tf->next = tmp_file_list;
+  tmp_file_list = tf;
+  oname = tf->name;
+  memcpy (tf->name, "ldXXXXXX", sizeof (tf->name));
+
+#ifdef HAVE_MKSTEMP
+  fd = mkstemp (oname);
+#else
+  oname = mktemp (oname);
+  if (oname == NULL)
+    return FALSE;
+  fd = open (oname, O_RDWR | O_CREAT | O_EXCL, 0600);
+#endif
+  if (fd == -1)
+    return FALSE;
+  close (fd);
+
+  /* Use fork() and exec() rather than system() so that we don't
+     need to worry about quoting args.  */
+  cmd[0] = "embedspu";
+  cmd[1] = flags;
+  cmd[2] = handle;
+  cmd[3] = entry->the_bfd->filename;
+  cmd[4] = oname;
+  cmd[5] = NULL;
+  if (trace_file_tries)
+    {
+      info_msg (_("running: %s \"%s\" \"%s\" \"%s\" \"%s\"\n"),
+		cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+      fflush (stdout);
+    }
+
+  pid = fork ();
+  if (pid == -1)
+    return FALSE;
+  if (pid == 0)
+    {
+      execvp (cmd[0], (char *const *) cmd);
+      perror (cmd[0]);
+      _exit (127);
+    }
+#ifdef HAVE_WAITPID
+#define WAITFOR(PID, STAT) waitpid (PID, STAT, 0)
+#else
+#define WAITFOR(PID, STAT) wait (STAT)
+#endif
+  if (WAITFOR (pid, &status) != pid
+      || !WIFEXITED (status)
+      || WEXITSTATUS (status) != 0)
+    return FALSE;
+#undef WAITFOR
+
+  old_stat_tail = stat_ptr->tail;
+  old_file_tail = input_file_chain.tail;
+  if (lang_add_input_file (oname, lang_input_file_is_file_enum, NULL) == NULL)
+    return FALSE;
+
+  /* lang_add_input_file put the new list entry at the end of the statement
+     and input file lists.  Move it to just after the current entry.  */
+  new_ent = *old_stat_tail;
+  *old_stat_tail = NULL;
+  stat_ptr->tail = old_stat_tail;
+  *old_file_tail = NULL;
+  input_file_chain.tail = old_file_tail;
+  new_ent->header.next = entry->header.next;
+  entry->header.next = new_ent;
+  new_ent->input_statement.next_real_file = entry->next_real_file;
+  entry->next_real_file = new_ent;
+
+  /* Ensure bfd sections are excluded from the output.  */
+  bfd_section_list_clear (entry->the_bfd);
+  entry->loaded = TRUE;
+  return TRUE;
+}
+
+EOF
+fi
+
 # Define some shell vars to insert bits of code into the standard elf
 # parse_args and list_options functions.
 #

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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