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]

Re: mn10300 relaxing bug


> How are we supposed to deal with this?

FYI I've come up with this patch so far, which looks for multiple
local symbols with the same address, so it can merge the flags.
Passes ld's make-check plus the application which showed the problem.

	* elf-m10300.c (elf32_mn10300_link_hash_entry): Add value.
	(elf32_mn10300_count_hash_table_entries): New.
	(elf32_mn10300_list_hash_table_entries): New.
	(sort_by_value): New.
	(mn10300_elf_relax_section): Don't skip data sections; restrict
	code-specific tests to code-specific areas so that potential
	indirect calls can be detected.  Check for multiple local symbols
	at the same address and merge their flags.
	(elf32_mn10300_link_hash_newfunc): Initialize value.

Index: elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.73
diff -p -U3 -r1.73 elf-m10300.c
--- elf-m10300.c	16 Mar 2006 12:20:15 -0000	1.73
+++ elf-m10300.c	4 Aug 2006 03:51:28 -0000
@@ -85,6 +85,9 @@ struct elf32_mn10300_link_hash_entry {
    prologue deleted.  */
 #define MN10300_DELETED_PROLOGUE_BYTES 0x2
   unsigned char flags;
+
+  /* Calculated value.  */
+  bfd_vma value;
 };
 
 /* We derive a hash table from the main elf linker hash table so
@@ -1602,6 +1605,42 @@ elf32_mn10300_finish_hash_table_entry (g
   return TRUE;
 }
 
+/* Used to count hash table entries.  */
+static bfd_boolean
+elf32_mn10300_count_hash_table_entries (struct bfd_hash_entry *gen_entry ATTRIBUTE_UNUSED,
+					PTR in_args)
+{
+  int *count = (int *)in_args;
+
+  (*count) ++;
+  return TRUE;
+}
+
+/* Used to enumerate hash table entries into a linear array.  */
+static bfd_boolean
+elf32_mn10300_list_hash_table_entries (struct bfd_hash_entry *gen_entry,
+				       PTR in_args)
+{
+  struct bfd_hash_entry ***ptr = (struct bfd_hash_entry ***) in_args;
+
+  **ptr = gen_entry;
+  (*ptr) ++;
+  return TRUE;
+}
+
+/* Used to sort the array created by the above.  */
+static int
+sort_by_value (const void *va, const void *vb)
+{
+  struct elf32_mn10300_link_hash_entry *a
+    = *(struct elf32_mn10300_link_hash_entry **)va;
+  struct elf32_mn10300_link_hash_entry *b
+    = *(struct elf32_mn10300_link_hash_entry **)vb;
+
+  return a->value - b->value;
+}
+
+
 /* This function handles relaxing for the mn10300.
 
    There are quite a few relaxing opportunities available on the mn10300:
@@ -1697,9 +1736,10 @@ mn10300_elf_relax_section (abfd, sec, li
 	      char *new_name;
 
 	      /* If there's nothing to do in this section, skip it.  */
-	      if (! (((section->flags & SEC_RELOC) != 0
-		      && section->reloc_count != 0)
-		     || (section->flags & SEC_CODE) != 0))
+	      if (! ((section->flags & SEC_RELOC) != 0
+		     && section->reloc_count != 0))
+		continue;
+	      if ((section->flags & SEC_ALLOC) == 0)
 		continue;
 
 	      /* Get cached copy of section contents if it exists.  */
@@ -1802,13 +1842,17 @@ mn10300_elf_relax_section (abfd, sec, li
 				   elf_sym_hashes (input_bfd)[r_index];
 			}
 
-		      /* If this is not a "call" instruction, then we
-			 should convert "call" instructions to "calls"
-			 instructions.  */
-		      code = bfd_get_8 (input_bfd,
-					contents + irel->r_offset - 1);
-		      if (code != 0xdd && code != 0xcd)
-			hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
+		      sym_name = hash->root.root.root.string;
+		      if ((section->flags & SEC_CODE) != 0)
+			{
+			  /* If this is not a "call" instruction, then we
+			     should convert "call" instructions to "calls"
+			     instructions.  */
+			  code = bfd_get_8 (input_bfd,
+					    contents + irel->r_offset - 1);
+			  if (code != 0xdd && code != 0xcd)
+			    hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
+			}
 
 		      /* If this is a jump/call, then bump the
 			 direct_calls counter.  Else force "call" to
@@ -1901,6 +1945,7 @@ mn10300_elf_relax_section (abfd, sec, li
 			  free (new_name);
 			  compute_function_info (input_bfd, hash,
 						 isym->st_value, contents);
+			  hash->value = isym->st_value;
 			}
 		    }
 
@@ -1962,6 +2007,44 @@ mn10300_elf_relax_section (abfd, sec, li
 					elf32_mn10300_finish_hash_table_entry,
 					link_info);
 
+      {
+	/* This section of code collects all our local symbols, sorts
+	   them by value, and looks for multiple symbols referring to
+	   the same address.  For those symbols, the flags are merged.
+	   At this point, the only flag that can be set is
+	   MN10300_CONVERT_CALL_TO_CALLS, so we simply OR the flags
+	   together.  */
+	int static_count = 0, i;
+	struct elf32_mn10300_link_hash_entry **entries;
+	struct elf32_mn10300_link_hash_entry **ptr;
+
+	elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
+					  elf32_mn10300_count_hash_table_entries,
+					  &static_count);
+
+	entries = (struct elf32_mn10300_link_hash_entry **)
+	  bfd_malloc (static_count * sizeof (struct elf32_mn10300_link_hash_entry *));
+
+	ptr = entries;
+	elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
+					  elf32_mn10300_list_hash_table_entries,
+					  &ptr);
+
+	qsort (entries, static_count, sizeof(entries[0]), sort_by_value);
+
+	for (i=0; i<static_count-1; i++)
+	  if (entries[i]->value && entries[i]->value == entries[i+1]->value)
+	    {
+	      int v = entries[i]->flags;
+	      int j;
+	      for (j=i+1; j<static_count && entries[j]->value == entries[i]->value; j++)
+		v |= entries[j]->flags;
+	      for (j=i; j<static_count && entries[j]->value == entries[i]->value; j++)
+		entries[j]->flags = v;
+	      i = j-1;
+	    }
+      }
+
       /* All entries in the hash table are fully initialized.  */
       hash_table->flags |= MN10300_HASH_ENTRIES_INITIALIZED;
 
@@ -3677,6 +3759,7 @@ elf32_mn10300_link_hash_newfunc (entry, 
       ret->movm_args = 0;
       ret->movm_stack_size = 0;
       ret->flags = 0;
+      ret->value = 0;
     }
 
   return (struct bfd_hash_entry *) ret;


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