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]
Other format: [Raw text]

Re: bfd/elf-m10300.c: odd code


On May 27, 2004, Alexandre Oliva <aoliva@redhat.com> wrote:

> Err...  I thought this patch had gone in a while ago, but it doesn't
> look like it.  I'm going ahead and checking this in.  Tested on
> i686-pc-linux-gnu.

Here's another fix for mn10300 relaxation problems.  We did function
relaxation using custom calling conventions (i.e., merging movm into
the caller) even for dynamic symbols.  Also, C++ thunk code calls a
local alias to a global function, so we relaxed the thunk without
realizing we were actually relaxing the global function.  Can't do
that.  I'm not entirely sure this patch will cover correctly all cases
(e.g., can we ever decide to use custom calling conventions for a
global symbol?), but this significantly improves C++ test results with
-mrelax, so I'm going ahead and checking it in.

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* elf-m10300.c (elf32_mn10300_finish_hash_table_entry): Avoid
	custom calling conventions for dynamic symbols.
	(mn10300_elf_relax_section): Avoid relaxing a function as a local
	symbol if it's an alias to a global one.

Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.50
diff -u -p -r1.50 elf-m10300.c
--- bfd/elf-m10300.c 27 May 2004 04:07:41 -0000 1.50
+++ bfd/elf-m10300.c 27 May 2004 06:13:06 -0000
@@ -1705,9 +1705,10 @@ mn10300_elf_relocate_section (output_bfd
 static bfd_boolean
 elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
      struct bfd_hash_entry *gen_entry;
-     PTR in_args ATTRIBUTE_UNUSED;
+     PTR in_args;
 {
   struct elf32_mn10300_link_hash_entry *entry;
+  struct bfd_link_info *link_info = (struct bfd_link_info *)in_args;
   unsigned int byte_count = 0;
 
   entry = (struct elf32_mn10300_link_hash_entry *) gen_entry;
@@ -1721,11 +1722,16 @@ elf32_mn10300_finish_hash_table_entry (g
     return TRUE;
 
   /* If there are no named calls to this symbol, or there's nothing we
-     can move from the function itself into the "call" instruction, then
-     note that all "call" instructions should be converted into "calls"
-     instructions and return.  */
+     can move from the function itself into the "call" instruction,
+     then note that all "call" instructions should be converted into
+     "calls" instructions and return.  If a symbol is available for
+     dynamic symbol resolution (overridable or overriding), avoid
+     custom calling conventions.  */
   if (entry->direct_calls == 0
-      || (entry->stack_size == 0 && entry->movm_args == 0))
+      || (entry->stack_size == 0 && entry->movm_args == 0)
+      || (elf_hash_table (link_info)->dynamic_sections_created
+	  && ELF_ST_VISIBILITY (entry->root.other) != STV_INTERNAL
+	  && ELF_ST_VISIBILITY (entry->root.other) != STV_HIDDEN))
     {
       /* Make a note that we should convert "call" instructions to "calls"
 	 instructions for calls to this symbol.  */
@@ -2000,6 +2006,11 @@ mn10300_elf_relax_section (abfd, sec, li
 		  sec_shndx = _bfd_elf_section_from_bfd_section (input_bfd,
 								 section);
 
+		  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+			      - symtab_hdr->sh_info);
+		  hashes = elf_sym_hashes (input_bfd);
+		  end_hashes = hashes + symcount;
+
 		  /* Look at each function defined in this section and
 		     update info for that function.  */
 		  isymend = isymbuf + symtab_hdr->sh_info;
@@ -2010,6 +2021,22 @@ mn10300_elf_relax_section (abfd, sec, li
 			{
 			  struct elf_link_hash_table *elftab;
 			  bfd_size_type amt;
+			  struct elf_link_hash_entry **lhashes = hashes;
+
+			  /* Skip a local symbol if it aliases a
+			     global one.  */
+			  for (; lhashes < end_hashes; lhashes++)
+			    {
+			      hash = (struct elf32_mn10300_link_hash_entry *) *lhashes;
+			      if ((hash->root.root.type == bfd_link_hash_defined
+				   || hash->root.root.type == bfd_link_hash_defweak)
+				  && hash->root.root.u.def.section == section
+				  && hash->root.type == STT_FUNC
+				  && hash->root.root.u.def.value == isym->st_value)
+				break;
+			    }
+			  if (lhashes != end_hashes)
+			    continue;
 
 			  if (isym->st_shndx == SHN_UNDEF)
 			    sym_sec = bfd_und_section_ptr;
@@ -2047,10 +2074,6 @@ mn10300_elf_relax_section (abfd, sec, li
 			}
 		    }
 
-		  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
-			      - symtab_hdr->sh_info);
-		  hashes = elf_sym_hashes (input_bfd);
-		  end_hashes = hashes + symcount;
 		  for (; hashes < end_hashes; hashes++)
 		    {
 		      hash = (struct elf32_mn10300_link_hash_entry *) *hashes;
@@ -2104,10 +2127,10 @@ mn10300_elf_relax_section (abfd, sec, li
 	 the final initialization steps on each.  */
       elf32_mn10300_link_hash_traverse (hash_table,
 					elf32_mn10300_finish_hash_table_entry,
-					NULL);
+					link_info);
       elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
 					elf32_mn10300_finish_hash_table_entry,
-					NULL);
+					link_info);
 
       /* All entries in the hash table are fully initialized.  */
       hash_table->flags |= MN10300_HASH_ENTRIES_INITIALIZED;
-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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