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]

minor spu bugfix and tidy


This fixes a minor bug in SPU function call analysis in that a
function without a properly typed STT_FUNC symbol, with no stack frame
requirement, and called first as a tail-call, could be seen as
belonging to the caller function even if other functions called it.
I've also removed redundant output_bfd arguments on a number of
functions, and moved spu_elf_check_vma to where it belongs in the
file.  (I try to keep functions more or less in the order they are
called during the link process.)

bfd/
	* elf32-spu.c (spu_elf_create_sections): Remove output_bfd parameter.
	(spu_elf_find_overlays, spu_elf_size_stubs): Likewise
	(process_stubs, discover_functions, build_call_tree): Likewise.
	(spu_elf_stack_analysis): Likewise.
	(spu_elf_check_vma): Likewise.  Move.
	(struct call_info): Make "is_tail" a bitfield.
	(insert_callee): Clear fun->start and set fun->is_func if we find
	a non-tail call.
	* elf32-spu.h (spu_elf_create_sections): Update prototype.
	(spu_elf_find_overlays, spu_elf_size_stubs, spu_elf_check_vma): Ditto.
ld/
	* emultempl/spuelf.em: Update calls to elf32-spu.c funcs.

Index: bfd/elf32-spu.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-spu.c,v
retrieving revision 1.34
diff -u -p -r1.34 elf32-spu.c
--- bfd/elf32-spu.c	14 Mar 2008 04:42:16 -0000	1.34
+++ bfd/elf32-spu.c	20 Mar 2008 04:54:51 -0000
@@ -419,8 +419,7 @@ get_sym_h (struct elf_link_hash_entry **
    that the linker maps the sections to the right place in the output.  */
 
 bfd_boolean
-spu_elf_create_sections (bfd *output_bfd,
-			 struct bfd_link_info *info,
+spu_elf_create_sections (struct bfd_link_info *info,
 			 int stack_analysis,
 			 int emit_stack_syms)
 {
@@ -451,7 +450,7 @@ spu_elf_create_sections (bfd *output_bfd
 	  || !bfd_set_section_alignment (ibfd, s, 4))
 	return FALSE;
 
-      name_len = strlen (bfd_get_filename (output_bfd)) + 1;
+      name_len = strlen (bfd_get_filename (info->output_bfd)) + 1;
       size = 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4);
       size += (name_len + 3) & -4;
 
@@ -467,7 +466,7 @@ spu_elf_create_sections (bfd *output_bfd
       bfd_put_32 (ibfd, 1, data + 8);
       memcpy (data + 12, SPU_PLUGIN_NAME, sizeof (SPU_PLUGIN_NAME));
       memcpy (data + 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4),
-	      bfd_get_filename (output_bfd), name_len);
+	      bfd_get_filename (info->output_bfd), name_len);
       s->contents = data;
     }
 
@@ -492,7 +491,7 @@ sort_sections (const void *a, const void
 /* Identify overlays in the output bfd, and number them.  */
 
 bfd_boolean
-spu_elf_find_overlays (bfd *output_bfd, struct bfd_link_info *info)
+spu_elf_find_overlays (struct bfd_link_info *info)
 {
   struct spu_link_hash_table *htab = spu_hash_table (info);
   asection **alloc_sec;
@@ -500,15 +499,16 @@ spu_elf_find_overlays (bfd *output_bfd, 
   asection *s;
   bfd_vma ovl_end;
 
-  if (output_bfd->section_count < 2)
+  if (info->output_bfd->section_count < 2)
     return FALSE;
 
-  alloc_sec = bfd_malloc (output_bfd->section_count * sizeof (*alloc_sec));
+  alloc_sec
+    = bfd_malloc (info->output_bfd->section_count * sizeof (*alloc_sec));
   if (alloc_sec == NULL)
     return FALSE;
 
   /* Pick out all the alloced sections.  */
-  for (n = 0, s = output_bfd->sections; s != NULL; s = s->next)
+  for (n = 0, s = info->output_bfd->sections; s != NULL; s = s->next)
     if ((s->flags & SEC_ALLOC) != 0
 	&& (s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != SEC_THREAD_LOCAL
 	&& s->size != 0)
@@ -1043,9 +1043,7 @@ build_spuear_stubs (struct elf_link_hash
 /* Size or build stubs.  */
 
 static bfd_boolean
-process_stubs (bfd *output_bfd,
-	       struct bfd_link_info *info,
-	       bfd_boolean build)
+process_stubs (struct bfd_link_info *info, bfd_boolean build)
 {
   struct spu_link_hash_table *htab = spu_hash_table (info);
   bfd *ibfd;
@@ -1081,7 +1079,7 @@ process_stubs (bfd *output_bfd,
 	      || isec->reloc_count == 0)
 	    continue;
 
-	  if (!maybe_needs_stubs (isec, output_bfd))
+	  if (!maybe_needs_stubs (isec, info->output_bfd))
 	    continue;
 
 	  /* Get the relocs.  */
@@ -1180,8 +1178,7 @@ process_stubs (bfd *output_bfd,
 /* Allocate space for overlay call and return stubs.  */
 
 int
-spu_elf_size_stubs (bfd *output_bfd,
-		    struct bfd_link_info *info,
+spu_elf_size_stubs (struct bfd_link_info *info,
 		    void (*place_spu_section) (asection *, asection *,
 					       const char *),
 		    int non_overlay_stubs)
@@ -1194,7 +1191,7 @@ spu_elf_size_stubs (bfd *output_bfd,
   asection *stub;
 
   htab->non_overlay_stubs = non_overlay_stubs;
-  if (!process_stubs (output_bfd, info, FALSE))
+  if (!process_stubs (info, FALSE))
     return 0;
 
   elf_link_hash_traverse (&htab->elf, allocate_spuear_stubs, htab);
@@ -1392,9 +1389,8 @@ spu_elf_build_stubs (struct bfd_link_inf
   h = elf_link_hash_lookup (&htab->elf, "__ovly_return", FALSE, FALSE, FALSE);
   htab->ovly_return = h;
 
-  /* Write out all the stubs.  */
-  obfd = htab->ovtab->output_section->owner;
-  process_stubs (obfd, info, TRUE);
+  /* Fill in all the stubs.  */
+  process_stubs (info, TRUE);
 
   elf_link_hash_traverse (&htab->elf, build_spuear_stubs, htab);
   if (htab->stub_err)
@@ -1426,6 +1422,7 @@ spu_elf_build_stubs (struct bfd_link_inf
   p = htab->ovtab->contents;
   /* set low bit of .size to mark non-overlay area as present.  */
   p[7] = 1;
+  obfd = htab->ovtab->output_section->owner;
   for (s = obfd->sections; s != NULL; s = s->next)
     {
       unsigned int ovl_index = spu_elf_section_data (s)->u.o.ovl_index;
@@ -1476,6 +1473,28 @@ spu_elf_build_stubs (struct bfd_link_inf
   return TRUE;
 }
 
+/* Check that all loadable section VMAs lie in the range
+   LO .. HI inclusive.  */
+
+asection *
+spu_elf_check_vma (struct bfd_link_info *info, bfd_vma lo, bfd_vma hi)
+{
+  struct elf_segment_map *m;
+  unsigned int i;
+  bfd *abfd = info->output_bfd;
+
+  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+    if (m->p_type == PT_LOAD)
+      for (i = 0; i < m->count; i++)
+	if (m->sections[i]->size != 0
+	    && (m->sections[i]->vma < lo
+		|| m->sections[i]->vma > hi
+		|| m->sections[i]->vma + m->sections[i]->size - 1 > hi))
+	  return m->sections[i];
+
+  return NULL;
+}
+
 /* OFFSET in SEC (presumably) is the beginning of a function prologue.
    Search for stack adjusting insns, and return the sp delta.  */
 
@@ -1608,7 +1627,7 @@ struct call_info
 {
   struct function_info *fun;
   struct call_info *next;
-  int is_tail;
+  unsigned int is_tail : 1;
 };
 
 struct function_info
@@ -1910,8 +1929,12 @@ insert_callee (struct function_info *cal
       {
 	/* Tail calls use less stack than normal calls.  Retain entry
 	   for normal call over one for tail call.  */
-	if (p->is_tail > callee->is_tail)
-	  p->is_tail = callee->is_tail;
+	p->is_tail &= callee->is_tail;
+	if (!p->is_tail)
+	  {
+	    p->fun->start = NULL;
+	    p->fun->is_func = TRUE;
+	  }
 	return FALSE;
       }
   callee->next = caller->call_list;
@@ -2137,7 +2160,7 @@ interesting_section (asection *s, bfd *o
 /* Map address ranges in code sections to functions.  */
 
 static bfd_boolean
-discover_functions (bfd *output_bfd, struct bfd_link_info *info)
+discover_functions (struct bfd_link_info *info)
 {
   bfd *ibfd;
   int bfd_idx;
@@ -2203,7 +2226,7 @@ discover_functions (bfd *output_bfd, str
 	    asection *s;
 
 	    *p = s = bfd_section_from_elf_index (ibfd, sy->st_shndx);
-	    if (s != NULL && interesting_section (s, output_bfd))
+	    if (s != NULL && interesting_section (s, info->output_bfd))
 	      *psy++ = sy;
 	  }
       symcount = psy - psyms;
@@ -2245,7 +2268,7 @@ discover_functions (bfd *output_bfd, str
 	}
 
       for (sec = ibfd->sections; sec != NULL && !gaps; sec = sec->next)
-	if (interesting_section (sec, output_bfd))
+	if (interesting_section (sec, info->output_bfd))
 	  gaps |= check_function_ranges (sec, info);
     }
 
@@ -2263,7 +2286,7 @@ discover_functions (bfd *output_bfd, str
 	    continue;
 
 	  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
-	    if (interesting_section (sec, output_bfd)
+	    if (interesting_section (sec, info->output_bfd)
 		&& sec->reloc_count != 0)
 	      {
 		if (!mark_functions_via_relocs (sec, info, FALSE))
@@ -2290,7 +2313,7 @@ discover_functions (bfd *output_bfd, str
 
 	  gaps = FALSE;
 	  for (sec = ibfd->sections; sec != NULL && !gaps; sec = sec->next)
-	    if (interesting_section (sec, output_bfd))
+	    if (interesting_section (sec, info->output_bfd))
 	      gaps |= check_function_ranges (sec, info);
 	  if (!gaps)
 	    continue;
@@ -2316,7 +2339,7 @@ discover_functions (bfd *output_bfd, str
 	     the range of such functions to the beginning of the
 	     next symbol of interest.  */
 	  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
-	    if (interesting_section (sec, output_bfd))
+	    if (interesting_section (sec, info->output_bfd))
 	      {
 		struct _spu_elf_section_data *sec_data;
 		struct spu_elf_stack_info *sinfo;
@@ -2409,7 +2432,7 @@ call_graph_traverse (struct function_inf
 /* Populate call_list for each function.  */
 
 static bfd_boolean
-build_call_tree (bfd *output_bfd, struct bfd_link_info *info)
+build_call_tree (struct bfd_link_info *info)
 {
   bfd *ibfd;
 
@@ -2423,7 +2446,7 @@ build_call_tree (bfd *output_bfd, struct
 
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
 	{
-	  if (!interesting_section (sec, output_bfd)
+	  if (!interesting_section (sec, info->output_bfd)
 	      || sec->reloc_count == 0)
 	    continue;
 
@@ -2614,17 +2637,15 @@ sum_stack (struct function_info *fun,
 /* Provide an estimate of total stack required.  */
 
 static bfd_boolean
-spu_elf_stack_analysis (bfd *output_bfd,
-			struct bfd_link_info *info,
-			int emit_stack_syms)
+spu_elf_stack_analysis (struct bfd_link_info *info, int emit_stack_syms)
 {
   bfd *ibfd;
   bfd_vma max_stack = 0;
 
-  if (!discover_functions (output_bfd, info))
+  if (!discover_functions (info))
     return FALSE;
 
-  if (!build_call_tree (output_bfd, info))
+  if (!build_call_tree (info))
     return FALSE;
 
   info->callbacks->info (_("Stack size for call graph root nodes.\n"));
@@ -2679,7 +2700,7 @@ spu_elf_final_link (bfd *output_bfd, str
   struct spu_link_hash_table *htab = spu_hash_table (info);
 
   if (htab->stack_analysis
-      && !spu_elf_stack_analysis (output_bfd, info, htab->emit_stack_syms))
+      && !spu_elf_stack_analysis (info, htab->emit_stack_syms))
     info->callbacks->einfo ("%X%P: stack analysis error: %E\n");
 
   return bfd_elf_final_link (output_bfd, info);
@@ -3053,27 +3074,6 @@ spu_elf_modify_segment_map (bfd *abfd, s
   return TRUE;
 }
 
-/* Check that all loadable section VMAs lie in the range
-   LO .. HI inclusive.  */
-
-asection *
-spu_elf_check_vma (bfd *abfd, bfd_vma lo, bfd_vma hi)
-{
-  struct elf_segment_map *m;
-  unsigned int i;
-
-  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-    if (m->p_type == PT_LOAD)
-      for (i = 0; i < m->count; i++)
-	if (m->sections[i]->size != 0
-	    && (m->sections[i]->vma < lo
-		|| m->sections[i]->vma > hi
-		|| m->sections[i]->vma + m->sections[i]->size - 1 > hi))
-	  return m->sections[i];
-
-  return NULL;
-}
-
 /* Tweak the section type of .note.spu_name.  */
 
 static bfd_boolean
Index: bfd/elf32-spu.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-spu.h,v
retrieving revision 1.5
diff -u -p -r1.5 elf32-spu.h
--- bfd/elf32-spu.h	28 Jan 2008 05:59:24 -0000	1.5
+++ bfd/elf32-spu.h	20 Mar 2008 04:54:51 -0000
@@ -1,6 +1,6 @@
 /* SPU specific support for 32-bit ELF.
 
-   Copyright 2006, 2007 Free Software Foundation, Inc.
+   Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -54,11 +54,10 @@ struct _ovl_stream
 extern void spu_elf_plugin (int);
 extern bfd_boolean spu_elf_open_builtin_lib (bfd **,
 					     const struct _ovl_stream *);
-extern bfd_boolean spu_elf_create_sections (bfd *,
-					    struct bfd_link_info *, int, int);
-extern bfd_boolean spu_elf_find_overlays (bfd *, struct bfd_link_info *);
-extern int spu_elf_size_stubs (bfd *, struct bfd_link_info *,
+extern bfd_boolean spu_elf_create_sections (struct bfd_link_info *, int, int);
+extern bfd_boolean spu_elf_find_overlays (struct bfd_link_info *);
+extern int spu_elf_size_stubs (struct bfd_link_info *,
 			       void (*) (asection *, asection *, const char *),
 			       int);
 extern bfd_boolean spu_elf_build_stubs (struct bfd_link_info *, int);
-extern asection *spu_elf_check_vma (bfd *, bfd_vma, bfd_vma);
+extern asection *spu_elf_check_vma (struct bfd_link_info *, bfd_vma, bfd_vma);
Index: ld/emultempl/spuelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/spuelf.em,v
retrieving revision 1.17
diff -u -p -r1.17 spuelf.em
--- ld/emultempl/spuelf.em	14 Mar 2008 04:42:44 -0000	1.17
+++ ld/emultempl/spuelf.em	20 Mar 2008 04:55:34 -0000
@@ -75,7 +75,7 @@ spu_after_open (void)
   if (is_spu_target ()
       && !link_info.relocatable
       && link_info.input_bfds != NULL
-      && !spu_elf_create_sections (link_info.output_bfd, &link_info,
+      && !spu_elf_create_sections (&link_info,
 				   stack_analysis, emit_stack_syms))
     einfo ("%X%P: can not create note section: %E\n");
 
@@ -198,11 +198,11 @@ spu_before_allocation (void)
       one_lang_size_sections_pass (NULL, TRUE);
 
       /* Find overlays by inspecting section vmas.  */
-      if (spu_elf_find_overlays (link_info.output_bfd, &link_info))
+      if (spu_elf_find_overlays (&link_info))
 	{
 	  int ret;
 
-	  ret = spu_elf_size_stubs (link_info.output_bfd, &link_info,
+	  ret = spu_elf_size_stubs (&link_info,
 				    spu_place_special_section,
 				    non_overlay_stubs);
 	  if (ret == 0)
@@ -235,8 +235,7 @@ gld${EMULATION_NAME}_finish (void)
         {
 	  asection *s;
 
-	  s = spu_elf_check_vma (link_info.output_bfd,
-				 local_store_lo, local_store_hi);
+	  s = spu_elf_check_vma (&link_info, local_store_lo, local_store_hi);
 	  if (s != NULL)
 	    einfo ("%X%P: %A exceeds local store range\n", s);
 	}

-- 
Alan Modra
Australia Development Lab, IBM


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