x86 ifunc related excessive memory use

H.J. Lu hjl.tools@gmail.com
Thu Jun 18 14:18:00 GMT 2009
On Thu, Jun 18, 2009 at 5:24 AM, Alan Modra<amodra@bigpond.net.au> wrote:
> HJ, since your ifunc patches I can't even run "make check" on my x86
> box successfully.
>
> tmpdir/dump53.o: could not read symbols: Memory exhausted
> FAIL: ld-elf/64ksec
>
> A quick look says it is likely to be the fact that you don't free
> isymbuf in check_relocs.
>

I checked in this fix.

Thanks.


-- 
H.J.
---
2009-06-18  H.J. Lu  <hongjiu.lu@intel.com>

	* elf32-i386.c (elf_i386_check_relocs): Cache or free isymbuf.
	* elf64-x86-64.c (elf64_x86_64_check_relocs): Likewise.
-------------- next part --------------
2009-06-18  H.J. Lu  <hongjiu.lu@intel.com>

	* elf32-i386.c (elf_i386_check_relocs): Cache or free isymbuf.
	* elf64-x86-64.c (elf64_x86_64_check_relocs): Likewise.

Index: elf64-x86-64.c
===================================================================
--- elf64-x86-64.c	(revision 6172)
+++ elf64-x86-64.c	(working copy)
@@ -1094,7 +1094,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	      h = elf64_x86_64_get_local_sym_hash (htab, abfd, rel,
 						   TRUE);
 	      if (h == NULL)
-		return FALSE;
+		goto error_return;
 	      
 	      /* Fake a STT_GNU_IFUNC symbol.  */
 	      h->type = STT_GNU_IFUNC;
@@ -1134,7 +1134,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	    case R_X86_64_GOTPCREL:
 	    case R_X86_64_GOTPCREL64:
 	      if (!_bfd_elf_create_ifunc_sections (abfd, info))
-		return FALSE;
+		goto error_return;
 	      break;
 	    }
 
@@ -1164,7 +1164,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		      ? h->root.root.string : "a local symbol"),
 		     __FUNCTION__);
 		  bfd_set_error (bfd_error_bad_value);
-		  return FALSE;
+		  goto error_return;
 
 		case R_X86_64_64:
 		  h->non_got_ref = 1;
@@ -1178,7 +1178,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 			(abfd, info, sec, sreloc,
 			 &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs);
 		      if (sreloc == NULL)
-			return FALSE;
+			goto error_return;
 		    }
 		  break;
 
@@ -1201,7 +1201,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		  if (htab->elf.sgot == NULL
 		      && !_bfd_elf_create_got_section (htab->elf.dynobj,
 						       info))
-		    return FALSE;
+		    goto error_return;
 		  break;
 		}
 
@@ -1213,7 +1213,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 					 symtab_hdr, sym_hashes,
 					 &r_type, GOT_UNKNOWN,
 					 rel, rel_end, h))
-	return FALSE;
+	goto error_return;
 
       switch (r_type)
 	{
@@ -1230,7 +1230,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		 x86_64_elf_howto_table[r_type].name,
 		 (h) ? h->root.root.string : "a local symbol");
 	      bfd_set_error (bfd_error_bad_value);
-	      return FALSE;
+	      goto error_return;
 	    }
 	  break;
 
@@ -1290,7 +1290,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    local_got_refcounts = ((bfd_signed_vma *)
 					   bfd_zalloc (abfd, size));
 		    if (local_got_refcounts == NULL)
-		      return FALSE;
+		      goto error_return;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
 		    elf64_x86_64_local_tlsdesc_gotent (abfd)
 		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
@@ -1318,7 +1318,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    (*_bfd_error_handler)
 		      (_("%B: '%s' accessed both as normal and thread local symbol"),
 		       abfd, h ? h->root.root.string : "<local>");
-		    return FALSE;
+		    goto error_return;
 		  }
 	      }
 
@@ -1342,7 +1342,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		htab->elf.dynobj = abfd;
 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj,
 						info))
-		return FALSE;
+		goto error_return;
 	    }
 	  break;
 
@@ -1391,7 +1391,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		 x86_64_elf_howto_table[r_type].name,
 		 (h) ? h->root.root.string : "a local symbol");
 	      bfd_set_error (bfd_error_bad_value);
-	      return FALSE;
+	      goto error_return;
 	    }
 	  /* Fall through.  */
 
@@ -1467,7 +1467,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    (sec, htab->elf.dynobj, 3, abfd, /*rela?*/ TRUE);
 
 		  if (sreloc == NULL)
-		    return FALSE;
+		    goto error_return;
 		}
 
 	      /* If this is a global symbol, we count the number of
@@ -1487,7 +1487,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
 						 sec, r_symndx);
 		  if (s == NULL)
-		    return FALSE;
+		    goto error_return;
 
 		  /* Beware of type punned pointers vs strict aliasing
 		     rules.  */
@@ -1503,7 +1503,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		  p = ((struct elf_dyn_relocs *)
 		       bfd_alloc (htab->elf.dynobj, amt));
 		  if (p == NULL)
-		    return FALSE;
+		    goto error_return;
 		  p->next = *head;
 		  *head = p;
 		  p->sec = sec;
@@ -1521,7 +1521,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	     Reconstruct it for later use during GC.  */
 	case R_X86_64_GNU_VTINHERIT:
 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-	    return FALSE;
+	    goto error_return;
 	  break;
 
 	  /* This relocation describes which C++ vtable entries are actually
@@ -1530,7 +1530,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	  BFD_ASSERT (h != NULL);
 	  if (h != NULL
 	      && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-	    return FALSE;
+	    goto error_return;
 	  break;
 
 	default:
@@ -1538,7 +1538,25 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	}
     }
 
+   if (isymbuf != NULL
+       && (unsigned char *) isymbuf != symtab_hdr->contents)
+    {
+      if (!info->keep_memory)
+	free (isymbuf);
+      else
+	{
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
+	}
+    }
+
   return TRUE;
+
+error_return:
+   if (isymbuf != NULL
+       && (unsigned char *) isymbuf != symtab_hdr->contents)
+     free (isymbuf);
+   return FALSE;
 }
 
 /* Return the section that should be marked against GC for a given
Index: elf32-i386.c
===================================================================
--- elf32-i386.c	(revision 6172)
+++ elf32-i386.c	(working copy)
@@ -1313,7 +1313,7 @@ elf_i386_check_relocs (bfd *abfd,
 	      h = elf_i386_get_local_sym_hash (htab, abfd, rel,
 						   TRUE);
 	      if (h == NULL)
-		return FALSE;
+		goto error_return;
 	      
 	      /* Fake a STT_GNU_IFUNC symbol.  */
 	      h->type = STT_GNU_IFUNC;
@@ -1350,7 +1350,7 @@ elf_i386_check_relocs (bfd *abfd,
 	    case R_386_GOT32:
 	    case R_386_GOTOFF:
 	      if (!_bfd_elf_create_ifunc_sections (abfd, info))
-		return FALSE;
+		goto error_return;
 	      break;
 	    }
 
@@ -1380,7 +1380,7 @@ elf_i386_check_relocs (bfd *abfd,
 		      ? h->root.root.string : "a local symbol"),
 		     __FUNCTION__);
 		  bfd_set_error (bfd_error_bad_value);
-		  return FALSE;
+		  goto error_return;
 
 		case R_386_32:
 		  h->non_got_ref = 1;
@@ -1394,7 +1394,7 @@ elf_i386_check_relocs (bfd *abfd,
 			(abfd, info, sec, sreloc,
 			 &((struct elf_i386_link_hash_entry *) h)->dyn_relocs);
 		      if (sreloc == NULL)
-			return FALSE;
+			goto error_return;
 		    }
 		  break;
 
@@ -1411,7 +1411,7 @@ elf_i386_check_relocs (bfd *abfd,
 		  if (htab->elf.sgot == NULL
 		      && !_bfd_elf_create_got_section (htab->elf.dynobj,
 						       info))
-		    return FALSE;
+		    goto error_return;
 		  break;
 		}
 
@@ -1423,7 +1423,7 @@ elf_i386_check_relocs (bfd *abfd,
 				     symtab_hdr, sym_hashes,
 				     &r_type, GOT_UNKNOWN,
 				     rel, rel_end, h)) 
-	return FALSE;
+	goto error_return;
 
       switch (r_type)
 	{
@@ -1504,7 +1504,7 @@ elf_i386_check_relocs (bfd *abfd,
 			     + sizeof (bfd_vma) + sizeof(char));
 		    local_got_refcounts = bfd_zalloc (abfd, size);
 		    if (local_got_refcounts == NULL)
-		      return FALSE;
+		      goto error_return;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
 		    elf_i386_local_tlsdesc_gotent (abfd)
 		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
@@ -1535,7 +1535,7 @@ elf_i386_check_relocs (bfd *abfd,
 			 "thread local symbol"),
 		       abfd,
 		       h ? h->root.root.string : "<local>");
-		    return FALSE;
+		    goto error_return;
 		  }
 	      }
 
@@ -1557,7 +1557,7 @@ elf_i386_check_relocs (bfd *abfd,
 	      if (htab->elf.dynobj == NULL)
 		htab->elf.dynobj = abfd;
 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
-		return FALSE;
+		goto error_return;
 	    }
 	  if (r_type != R_386_TLS_IE)
 	    break;
@@ -1639,7 +1639,7 @@ elf_i386_check_relocs (bfd *abfd,
 		    (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ FALSE);
 
 		  if (sreloc == NULL)
-		    return FALSE;
+		    goto error_return;
 		}
 
 	      /* If this is a global symbol, we count the number of
@@ -1659,7 +1659,7 @@ elf_i386_check_relocs (bfd *abfd,
 		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
 						 sec, r_symndx);
 		  if (s == NULL)
-		    return FALSE;
+		    goto error_return;
 
 		  vpp = &elf_section_data (s)->local_dynrel;
 		  head = (struct elf_dyn_relocs **)vpp;
@@ -1671,7 +1671,7 @@ elf_i386_check_relocs (bfd *abfd,
 		  bfd_size_type amt = sizeof *p;
 		  p = bfd_alloc (htab->elf.dynobj, amt);
 		  if (p == NULL)
-		    return FALSE;
+		    goto error_return;
 		  p->next = *head;
 		  *head = p;
 		  p->sec = sec;
@@ -1689,7 +1689,7 @@ elf_i386_check_relocs (bfd *abfd,
 	     Reconstruct it for later use during GC.  */
 	case R_386_GNU_VTINHERIT:
 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-	    return FALSE;
+	    goto error_return;
 	  break;
 
 	  /* This relocation describes which C++ vtable entries are actually
@@ -1698,7 +1698,7 @@ elf_i386_check_relocs (bfd *abfd,
 	  BFD_ASSERT (h != NULL);
 	  if (h != NULL
 	      && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
-	    return FALSE;
+	    goto error_return;
 	  break;
 
 	default:
@@ -1706,7 +1706,25 @@ elf_i386_check_relocs (bfd *abfd,
 	}
     }
 
+   if (isymbuf != NULL
+       && (unsigned char *) isymbuf != symtab_hdr->contents)
+    {
+      if (!info->keep_memory)
+	free (isymbuf);
+      else
+	{
+	  /* Cache the symbols for elf_link_input_bfd.  */
+	  symtab_hdr->contents = (unsigned char *) isymbuf;
+	}
+    }
+
   return TRUE;
+
+error_return:
+   if (isymbuf != NULL
+       && (unsigned char *) isymbuf != symtab_hdr->contents)
+     free (isymbuf);
+   return FALSE;
 }
 
 /* Return the section that should be marked against GC for a given


More information about the Binutils mailing list