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]

ELF/m68k visibility handling in shared libraries


The linker didn't properly resolve pc-relative relocations against symbols
that are forced to be local due to visibility changes when creating a
shared library.

Andreas.

2002-11-29  Andreas Schwab  <schwab@suse.de>

	* elf32-m68k.c (struct elf_m68k_link_hash_table): Add sym_sec
	member.
	(elf_m68k_link_hash_table_create): Initialize it.
	(elf_m68k_check_relocs): Handle symbols that are forced to be
	local due to visibility changes.
	(elf_m68k_adjust_dynamic_symbol): Likewise.
	(elf_m68k_size_dynamic_sections): Likewise.
	(elf_m68k_discard_copies): Likewise.
	(elf_m68k_relocate_section): Likewise.

Index: bfd/elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.47
diff -u -p -a -u -p -a -r1.47 bfd/elf32-m68k.c
--- bfd/elf32-m68k.c	28 Nov 2002 11:55:40 -0000	1.47
+++ bfd/elf32-m68k.c	29 Nov 2002 22:09:51 -0000
@@ -277,6 +277,9 @@ struct elf_m68k_link_hash_entry
 struct elf_m68k_link_hash_table
 {
   struct elf_link_hash_table root;
+
+  /* Small local sym to section mapping cache.  */
+  struct sym_sec_cache sym_sec;
 };
 
 /* Declare this now that the above structures are defined.  */
@@ -349,6 +352,8 @@ elf_m68k_link_hash_table_create (abfd)
       return NULL;
     }
 
+  ret->sym_sec.abfd = NULL;
+
   return &ret->root.root;
 }
 
@@ -516,7 +521,8 @@ elf_m68k_check_relocs (abfd, info, sec, 
 	      if (h->got.refcount == 0)
 		{
 		  /* Make sure this symbol is output as a dynamic symbol.  */
-		  if (h->dynindx == -1)
+		  if (h->dynindx == -1
+		      && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 		    {
 		      if (!bfd_elf32_link_record_dynamic_symbol (info, h))
 			return false;
@@ -593,7 +599,8 @@ elf_m68k_check_relocs (abfd, info, sec, 
 	    }
 
 	  /* Make sure this symbol is output as a dynamic symbol.  */
-	  if (h->dynindx == -1)
+	  if (h->dynindx == -1
+	      && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 	    {
 	      if (!bfd_elf32_link_record_dynamic_symbol (info, h))
 		return false;
@@ -620,6 +627,7 @@ elf_m68k_check_relocs (abfd, info, sec, 
 		&& (sec->flags & SEC_ALLOC) != 0
 		&& h != NULL
 		&& (!info->symbolic
+		    || h->root.type == bfd_link_hash_defweak
 		    || (h->elf_link_hash_flags
 			& ELF_LINK_HASH_DEF_REGULAR) == 0)))
 	    {
@@ -694,17 +702,33 @@ elf_m68k_check_relocs (abfd, info, sec, 
 		 only called if we are using an m68kelf linker hash table,
 		 which means that h is really a pointer to an
 		 elf_m68k_link_hash_entry.  */
-	      if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8
- 		   || ELF32_R_TYPE (rel->r_info) == R_68K_PC16
- 		   || ELF32_R_TYPE (rel->r_info) == R_68K_PC32)
-		  && info->symbolic)
+	      if (ELF32_R_TYPE (rel->r_info) == R_68K_PC8
+		  || ELF32_R_TYPE (rel->r_info) == R_68K_PC16
+		  || ELF32_R_TYPE (rel->r_info) == R_68K_PC32)
 		{
-		  struct elf_m68k_link_hash_entry *eh;
 		  struct elf_m68k_pcrel_relocs_copied *p;
+		  struct elf_m68k_pcrel_relocs_copied **head;
+
+		  if (h != NULL)
+		    {
+		      struct elf_m68k_link_hash_entry *eh
+			= (struct elf_m68k_link_hash_entry *) h;
+		      head = &eh->pcrel_relocs_copied;
+		    }
+		  else
+		    {
+		      asection *s;
+		      s = (bfd_section_from_r_symndx
+			   (abfd, &elf_m68k_hash_table (info)->sym_sec,
+			    sec, r_symndx));
+		      if (s == NULL)
+			return false;
 
-		  eh = (struct elf_m68k_link_hash_entry *) h;
+		      head = ((struct elf_m68k_pcrel_relocs_copied **)
+			      &elf_section_data (s)->local_dynrel);
+		    }
 
-		  for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
+		  for (p = *head; p != NULL; p = p->next)
 		    if (p->section == sreloc)
 		      break;
 
@@ -714,8 +738,8 @@ elf_m68k_check_relocs (abfd, info, sec, 
 			   bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
 		      if (p == NULL)
 			return false;
-		      p->next = eh->pcrel_relocs_copied;
-		      eh->pcrel_relocs_copied = p;
+		      p->next = *head;
+		      *head = p;
 		      p->section = sreloc;
 		      p->count = 0;
 		    }
@@ -950,7 +974,8 @@ elf_m68k_adjust_dynamic_symbol (info, h)
 	}
 
       /* Make sure this symbol is output as a dynamic symbol.  */
-      if (h->dynindx == -1)
+      if (h->dynindx == -1
+	  && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 	{
 	  if (! bfd_elf32_link_record_dynamic_symbol (info, h))
 	    return false;
@@ -1121,14 +1146,16 @@ elf_m68k_size_dynamic_sections (output_b
 	s->_raw_size = 0;
     }
 
-  /* If this is a -Bsymbolic shared link, then we need to discard all PC
-     relative relocs against symbols defined in a regular object.  We
-     allocated space for them in the check_relocs routine, but we will not
-     fill them in in the relocate_section routine.  */
-  if (info->shared && info->symbolic)
+  /* If this is a -Bsymbolic shared link, then we need to discard all
+     PC relative relocs against symbols defined in a regular object.
+     For the normal shared case we discard the PC relative relocs
+     against symbols that have become local due to visibility changes.
+     We allocated space for them in the check_relocs routine, but we
+     will not fill them in in the relocate_section routine.  */
+  if (info->shared)
     elf_m68k_link_hash_traverse (elf_m68k_hash_table (info),
 				 elf_m68k_discard_copies,
-				 (PTR) NULL);
+				 (PTR) info);
 
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
@@ -1255,23 +1282,28 @@ elf_m68k_size_dynamic_sections (output_b
 }
 
 /* This function is called via elf_m68k_link_hash_traverse if we are
-   creating a shared object with -Bsymbolic.  It discards the space
-   allocated to copy PC relative relocs against symbols which are defined
-   in regular objects.  We allocated space for them in the check_relocs
-   routine, but we won't fill them in in the relocate_section routine.  */
+   creating a shared object.  In the -Bsymbolic case it discards the
+   space allocated to copy PC relative relocs against symbols which
+   are defined in regular objects.  For the normal shared case, if
+   discards space for pc-relative relocs that have become local due to
+   symbol visibility changes.  We allocated space for them in the
+   check_relocs routine, but we won't fill them in in the
+   relocate_section routine.  */
 
 static boolean
-elf_m68k_discard_copies (h, ignore)
+elf_m68k_discard_copies (h, inf)
      struct elf_m68k_link_hash_entry *h;
-     PTR ignore ATTRIBUTE_UNUSED;
+     PTR inf;
 {
+  struct bfd_link_info *info = (struct bfd_link_info *) inf;
   struct elf_m68k_pcrel_relocs_copied *s;
 
   if (h->root.root.type == bfd_link_hash_warning)
     h = (struct elf_m68k_link_hash_entry *) h->root.root.u.i.link;
 
-  /* We only discard relocs for symbols defined in a regular object.  */
-  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+      || (!info->symbolic
+	  && (h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0))
     return true;
 
   for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
@@ -1591,7 +1623,9 @@ elf_m68k_relocate_section (output_bfd, i
 	case R_68K_PC8:
 	case R_68K_PC16:
 	case R_68K_PC32:
-	  if (h == NULL)
+	  if (h == NULL
+	      || (info->shared
+		  && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
 	    break;
 	  /* Fall through.  */
 	case R_68K_8:

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


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