* emultempl/spuelf.em (embedded_spu_file): Deduce embedspu program
[deliverable/binutils-gdb.git] / ld / emultempl / spuelf.em
index d6681adabe5879f99ab88d5363cccf0a6a726cd7..3266f65e21db802ca541f9f327df4d1ecaae0b1e 100644 (file)
@@ -34,6 +34,12 @@ static int non_overlay_stubs = 0;
 /* Whether to emit symbols for stubs.  */
 static int emit_stub_syms = 0;
 
+/* Non-zero to perform stack space analysis.  */
+static int stack_analysis = 0;
+
+/* Whether to emit symbols with stack requirements for each function.  */
+static int emit_stack_syms = 0;
+
 /* Range of valid addresses for loadable sections.  */
 static bfd_vma local_store_lo = 0;
 static bfd_vma local_store_hi = 0x3ffff;
@@ -70,7 +76,8 @@ spu_after_open (void)
   if (is_spu_target ()
       && !link_info.relocatable
       && link_info.input_bfds != NULL
-      && !spu_elf_create_sections (output_bfd, &link_info))
+      && !spu_elf_create_sections (output_bfd, &link_info,
+                                  stack_analysis, emit_stack_syms))
     einfo ("%X%P: can not create note section: %E\n");
 
   gld${EMULATION_NAME}_after_open ();
@@ -187,7 +194,7 @@ spu_before_allocation (void)
          asection *stub, *ovtab;
 
          if (!spu_elf_size_stubs (output_bfd, &link_info, non_overlay_stubs,
-                                  &stub, &ovtab, &toe))
+                                  stack_analysis, &stub, &ovtab, &toe))
            einfo ("%X%P: can not size overlay stubs: %E\n");
 
          if (stub != NULL)
@@ -238,6 +245,203 @@ 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);
+}
+
+static const char *
+base_name (const char *path)
+{
+  const char *file = strrchr (path, '/');
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  {
+    char *bslash = strrchr (path, '\\');
+
+    if (file == NULL || (bslash != NULL && bslash > file))
+      file = bslash;
+    if (file == NULL
+       && path[0] != '\0'
+       && path[1] == ':')
+      file = path + 1;
+  }
+#endif
+  if (file == NULL)
+    file = path;
+  else
+    ++file;
+  return file;
+}
+
+/* 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;
+  lang_input_statement_type *search;
+  const char *prefix;
+  size_t prefix_len;
+
+  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 = base_name (entry->the_bfd->filename);
+
+  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);
+
+  for (search = (lang_input_statement_type *) input_file_chain.head;
+       search != NULL;
+       search = (lang_input_statement_type *) search->next_real_file)
+    {
+      const char *infile = base_name (search->filename);
+
+      if (infile != NULL
+         && strncmp (infile, "crtbegin", 8) == 0)
+       {
+         if (infile[8] == 'S')
+           flags = concat (flags, " -fPIC", NULL);
+         else if (infile[8] == 'T')
+           flags = concat (flags, " -fpie", NULL);
+         break;
+       }
+    }
+
+  /* Use fork() and exec() rather than system() so that we don't
+     need to worry about quoting args.  */
+  prefix = base_name (program_name);
+  prefix_len = strlen (prefix);
+  if (prefix_len > 2
+      && (prefix[prefix_len - 2] == 'l'
+         || prefix[prefix_len - 2] == 'L')
+      && (prefix[prefix_len - 1] == 'd'
+         || prefix[prefix_len - 1] == 'D'))
+    {
+      cmd[0] = xmalloc (prefix_len + 7);
+      memcpy (cmd[0], prefix, prefix_len - 2);
+      memcpy (cmd[0] + prefix_len - 2, "embedspu", 9);
+    }
+  else
+    {
+      prefix_len = 0;
+      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);
+      if (prefix_len != 0)
+       {
+         cmd[0] = "embedspu";
+         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.
 #
@@ -247,6 +451,8 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_SPU_STUB_SYMS           (OPTION_SPU_NO_OVERLAYS + 1)
 #define OPTION_SPU_NON_OVERLAY_STUBS   (OPTION_SPU_STUB_SYMS + 1)
 #define OPTION_SPU_LOCAL_STORE         (OPTION_SPU_NON_OVERLAY_STUBS + 1)
+#define OPTION_SPU_STACK_ANALYSIS      (OPTION_SPU_LOCAL_STORE + 1)
+#define OPTION_SPU_STACK_SYMS          (OPTION_SPU_STACK_ANALYSIS + 1)
 '
 
 PARSE_AND_LIST_LONGOPTS='
@@ -255,6 +461,8 @@ PARSE_AND_LIST_LONGOPTS='
   { "emit-stub-syms", no_argument, NULL, OPTION_SPU_STUB_SYMS },
   { "extra-overlay-stubs", no_argument, NULL, OPTION_SPU_NON_OVERLAY_STUBS },
   { "local-store", required_argument, NULL, OPTION_SPU_LOCAL_STORE },
+  { "stack-analysis", no_argument, NULL, OPTION_SPU_STACK_ANALYSIS },
+  { "emit-stack-syms", no_argument, NULL, OPTION_SPU_STACK_SYMS },
 '
 
 PARSE_AND_LIST_OPTIONS='
@@ -263,7 +471,9 @@ PARSE_AND_LIST_OPTIONS='
   --no-overlays         No overlay handling.\n\
   --emit-stub-syms      Add symbols on overlay call stubs.\n\
   --extra-overlay-stubs Add stubs on all calls out of overlay regions.\n\
-  --local-store=lo:hi   Valid address range.\n"
+  --local-store=lo:hi   Valid address range.\n\
+  --stack-analysis      Estimate maximum stack requirement.\n\
+  --emit-stack-syms     Add __stack_func giving stack needed for each func.\n"
                   ));
 '
 
@@ -297,6 +507,14 @@ PARSE_AND_LIST_ARGS_CASES='
        einfo (_("%P%F: invalid --local-store address range `%s'\''\n"), optarg);
       }
       break;
+
+    case OPTION_SPU_STACK_ANALYSIS:
+      stack_analysis = 1;
+      break;
+
+    case OPTION_SPU_STACK_SYMS:
+      emit_stack_syms = 1;
+      break;
 '
 
 LDEMUL_AFTER_OPEN=spu_after_open
This page took 0.025681 seconds and 4 git commands to generate.