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]

Powerpc64 dynreloc miscount and aborts building shared lib


This fixes an error in bfd_section_from_r_symndx, a function that is
supposed to find the section of a reloc symbol.  It has a rather
curious interface in that if the reloc symbol has no real bfd section
(or if the reloc has no symbol), then it returns a default section
passed in as one of the input parameters.  It also caches r_symndx
to section mapping.  The problem with this is that a reloc with no
symbol causes the default section to be cached, which is wrong for a
following call with a different default section.

This can result in powerpc64 "dynreloc miscount" errors and aborts
(line 10985 of elf64-ppc.c) if the section size for dynamic relocs
isn't as expected.

	* elf-bfd.h (struct sym_sec_cache): Delete "sec".  Add "shndx".
	* elf.c (bfd_section_from_r_symndx): Don't cache bfd section of
	symbol.  Instead cache ELF section index.  Remove redundant
	checks of st_shndx.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.237
diff -u -p -r1.237 elf-bfd.h
--- bfd/elf-bfd.h	13 Jul 2007 10:44:12 -0000	1.237
+++ bfd/elf-bfd.h	18 Jul 2007 10:34:42 -0000
@@ -423,7 +423,7 @@ struct sym_sec_cache
 {
   bfd *abfd;
   unsigned long indx[LOCAL_SYM_CACHE_SIZE];
-  asection *sec[LOCAL_SYM_CACHE_SIZE];
+  unsigned int shndx[LOCAL_SYM_CACHE_SIZE];
 };
 
 /* Constant information held for an ELF backend.  */
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.398
diff -u -p -r1.398 elf.c
--- bfd/elf.c	13 Jul 2007 10:44:12 -0000	1.398
+++ bfd/elf.c	18 Jul 2007 11:03:08 -0000
@@ -2273,36 +2273,35 @@ bfd_section_from_r_symndx (bfd *abfd,
 			   asection *sec,
 			   unsigned long r_symndx)
 {
-  Elf_Internal_Shdr *symtab_hdr;
-  unsigned char esym[sizeof (Elf64_External_Sym)];
-  Elf_External_Sym_Shndx eshndx;
-  Elf_Internal_Sym isym;
   unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
+  asection *s;
 
-  if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
-    return cache->sec[ent];
+  if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
+    {
+      Elf_Internal_Shdr *symtab_hdr;
+      unsigned char esym[sizeof (Elf64_External_Sym)];
+      Elf_External_Sym_Shndx eshndx;
+      Elf_Internal_Sym isym;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
-			    &isym, esym, &eshndx) == NULL)
-    return NULL;
+      symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+      if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
+				&isym, esym, &eshndx) == NULL)
+	return NULL;
 
-  if (cache->abfd != abfd)
-    {
-      memset (cache->indx, -1, sizeof (cache->indx));
-      cache->abfd = abfd;
-    }
-  cache->indx[ent] = r_symndx;
-  cache->sec[ent] = sec;
-  if ((isym.st_shndx != SHN_UNDEF && isym.st_shndx < SHN_LORESERVE)
-      || isym.st_shndx > SHN_HIRESERVE)
-    {
-      asection *s;
-      s = bfd_section_from_elf_index (abfd, isym.st_shndx);
-      if (s != NULL)
-	cache->sec[ent] = s;
+      if (cache->abfd != abfd)
+	{
+	  memset (cache->indx, -1, sizeof (cache->indx));
+	  cache->abfd = abfd;
+	}
+      cache->indx[ent] = r_symndx;
+      cache->shndx[ent] = isym.st_shndx;
     }
-  return cache->sec[ent];
+
+  s = bfd_section_from_elf_index (abfd, cache->shndx[ent]);
+  if (s != NULL)
+    return s;
+
+  return sec;
 }
 
 /* Given an ELF section number, retrieve the corresponding BFD

-- 
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]