Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes)
Date: 2006-12-04
Initial Package Version: 2.17
Upstream Status: From Upstream
Origin: cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co \
		-rbinutils-2_17-branch binutils
Description: This is the binutils-2_17-branch (bug fix branch) update,
compared from binutils-2.17-release and binutils-2_17-branch with all
the fluff removed (CVS entries, maintainer files, etc). This patch
should be updated periodically.

2006-08-08  Nick Clifton  <nickc@redhat.com>

        PR binutils/2724
        * bfd/coffcode.h (coff_new_section_hook): Only modify the section
        symbol of sections which were created by the user.

2006-07-19  Alan Modra  <amodra@bigpond.net.au>

        * bfd/bfd-in.h (enum notice_asneeded_action): Define.
        * bfd/bfd-in2.h: Regenerate.
        * bfd/elflink.c (elf_link_add_object_symbols): Call linker "notice"
        function with NULL name for as-needed handling.

2006-07-12  Matthew R. Dempsky  <mrd@alkemio.org>

        * bfd/cpu-m68k.c (bfd_m68k_compatible): Handle CPU32.

2006-08-15  Nick Clifton  <nickc@redhat.com>

        PR binutils/3039
        * binutils/wrstabs.c (stab_tag_type): Initialize 'size'.

2006-07-19  Mat Hostetter  <mat@lcs.mit.edu>

        * gas/symbols.c (report_op_error): Fix pasto.  Don't use as_bad_where
        when file and line unknown.

2006-07-19  Alan Modra  <amodra@bigpond.net.au>

        * ld/ld.h (handle_asneeded_cref): Declare.
        * ld/ldcref.c: Include objalloc.h.
        (old_table, old_tab, alloc_mark): New variables.
        (tabsize, entsize, refsize, old_symcount): Likewise.
        (add_cref): Use bfd_hash_allocate for refs.
        (handle_asneeded_cref): New function.
        * ld/ldmain.c (notice): Call handle_asneeded_cref for NULL name.

2006-07-04  Daniel Jacobowitz  <dan@codesourcery.com>

        Backport:
        2006-05-19  Alan Modra  <amodra@bigpond.net.au>
        * ld/ldlang.c (lang_size_sections_1): Don't check mem regions for
        os->ignored sections.

2006-07-12  Richard Sandiford  <richard@codesourcery.com>

        * ld/testsuite/ld-m68k/merge-ok-1c.d: New test.
        * ld/testsuite/ld-m68k/m68k.exp: Run it.

2006-07-04  Daniel Jacobowitz  <dan@codesourcery.com>

        Backport:
        2006-05-19  Alan Modra  <amodra@bigpond.net.au>
        * ld/testsuite/ld-scripts/empty-orphan.d: Update again.

        * ld/testsuite/ld-scripts/empty-orphan.t: Discard .reginfo.
        * ld/testsuite/ld-scripts/empty-orphan.d: Update.

diff -Naur binutils-2.17.orig/bfd/bfd-in.h binutils-2.17/bfd/bfd-in.h
--- binutils-2.17.orig/bfd/bfd-in.h	2006-03-16 12:20:15.000000000 +0000
+++ binutils-2.17/bfd/bfd-in.h	2006-12-04 05:09:53.000000000 +0000
@@ -636,6 +636,12 @@
   DYN_NO_NEEDED = 8
 };
 
+enum notice_asneeded_action {
+  notice_as_needed,
+  notice_not_needed,
+  notice_needed
+};
+
 extern bfd_boolean bfd_elf_record_link_assignment
   (bfd *, struct bfd_link_info *, const char *, bfd_boolean,
    bfd_boolean);
diff -Naur binutils-2.17.orig/bfd/bfd-in2.h binutils-2.17/bfd/bfd-in2.h
--- binutils-2.17.orig/bfd/bfd-in2.h	2006-03-26 00:38:42.000000000 +0000
+++ binutils-2.17/bfd/bfd-in2.h	2006-12-04 05:09:53.000000000 +0000
@@ -643,6 +643,12 @@
   DYN_NO_NEEDED = 8
 };
 
+enum notice_asneeded_action {
+  notice_as_needed,
+  notice_not_needed,
+  notice_needed
+};
+
 extern bfd_boolean bfd_elf_record_link_assignment
   (bfd *, struct bfd_link_info *, const char *, bfd_boolean,
    bfd_boolean);
diff -Naur binutils-2.17.orig/bfd/coffcode.h binutils-2.17/bfd/coffcode.h
--- binutils-2.17.orig/bfd/coffcode.h	2005-10-25 17:40:09.000000000 +0000
+++ binutils-2.17/bfd/coffcode.h	2006-12-04 05:09:53.000000000 +0000
@@ -1546,9 +1546,6 @@
 static bfd_boolean
 coff_new_section_hook (bfd * abfd, asection * section)
 {
-  combined_entry_type *native;
-  bfd_size_type amt;
-
   section->alignment_power = COFF_DEFAULT_SECTION_ALIGNMENT_POWER;
 
 #ifdef RS6000COFF_C
@@ -1560,27 +1557,34 @@
     section->alignment_power = bfd_xcoff_data_align_power (abfd);
 #endif
 
-  /* Allocate aux records for section symbols, to store size and
-     related info.
-
-     @@ The 10 is a guess at a plausible maximum number of aux entries
-     (but shouldn't be a constant).  */
-  amt = sizeof (combined_entry_type) * 10;
-  native = bfd_zalloc (abfd, amt);
-  if (native == NULL)
-    return FALSE;
-
-  /* We don't need to set up n_name, n_value, or n_scnum in the native
-     symbol information, since they'll be overridden by the BFD symbol
-     anyhow.  However, we do need to set the type and storage class,
-     in case this symbol winds up getting written out.  The value 0
-     for n_numaux is already correct.  */
-
-  native->u.syment.n_type = T_NULL;
-  native->u.syment.n_sclass = C_STAT;
+  /* PR binutils/2724: Only real sections have a symbol that
+     has the coff_symbol_type structure allocated for it.  */
+  if (! bfd_is_const_section (section))
+    {
+      combined_entry_type *native;
+      bfd_size_type amt;
+
+      /* Allocate aux records for section symbols, to store size and
+	 related info.
+
+	 @@ The 10 is a guess at a plausible maximum number of aux entries
+	 (but shouldn't be a constant).  */
+      amt = sizeof (combined_entry_type) * 10;
+      native = bfd_zalloc (abfd, amt);
+      if (native == NULL)
+	return FALSE;
 
-  coffsymbol (section->symbol)->native = native;
+      /* We don't need to set up n_name, n_value, or n_scnum in the native
+	 symbol information, since they'll be overridden by the BFD symbol
+	 anyhow.  However, we do need to set the type and storage class,
+	 in case this symbol winds up getting written out.  The value 0
+	 for n_numaux is already correct.  */
+      native->u.syment.n_type = T_NULL;
+      native->u.syment.n_sclass = C_STAT;
 
+      coffsymbol (section->symbol)->native = native;
+    }
+  
   coff_set_custom_section_alignment (abfd, section,
 				     coff_section_alignment_table,
 				     coff_section_alignment_table_size);
diff -Naur binutils-2.17.orig/bfd/cpu-m68k.c binutils-2.17/bfd/cpu-m68k.c
--- binutils-2.17.orig/bfd/cpu-m68k.c	2006-03-25 10:24:27.000000000 +0000
+++ binutils-2.17/bfd/cpu-m68k.c	2006-12-04 05:09:53.000000000 +0000
@@ -202,6 +202,9 @@
   if (a->mach <= bfd_mach_m68060 && b->mach <= bfd_mach_m68060)
     /* Merge m68k machine. */
     return a->mach > b->mach ? a : b;
+  else if (a->mach == bfd_mach_cpu32 && b->mach == bfd_mach_cpu32)
+    /* CPU32 is compatible with itself. */
+    return a;
   else if (a->mach >= bfd_mach_mcf_isa_a_nodiv
 	   && b->mach >= bfd_mach_mcf_isa_a_nodiv)
     {
diff -Naur binutils-2.17.orig/bfd/elflink.c binutils-2.17/bfd/elflink.c
--- binutils-2.17.orig/bfd/elflink.c	2006-05-22 15:06:36.000000000 +0000
+++ binutils-2.17/bfd/elflink.c	2006-12-04 05:09:53.000000000 +0000
@@ -3496,6 +3496,13 @@
       if (alloc_mark == NULL)
 	goto error_free_vers;
 
+      /* Make a special call to the linker "notice" function to
+	 tell it that we are about to handle an as-needed lib.  */
+      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
+				       notice_as_needed))
+	return FALSE;
+
+
       /* Clone the symbol table and sym hashes.  Remember some
 	 pointers into the symbol table, and dynamic symbol count.  */
       old_hash = (char *) old_tab + tabsize;
@@ -4169,6 +4176,12 @@
 	    }
 	}
 
+      /* Make a special call to the linker "notice" function to
+	 tell it that symbols added for crefs may need to be removed.  */
+      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
+				       notice_not_needed))
+	return FALSE;
+
       free (old_tab);
       objalloc_free_block ((struct objalloc *) htab->root.table.memory,
 			   alloc_mark);
@@ -4179,6 +4192,9 @@
 
   if (old_tab != NULL)
     {
+      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
+				       notice_needed))
+	return FALSE;
       free (old_tab);
       old_tab = NULL;
     }
diff -Naur binutils-2.17.orig/binutils/wrstabs.c binutils-2.17/binutils/wrstabs.c
--- binutils-2.17.orig/binutils/wrstabs.c	2006-03-16 12:20:16.000000000 +0000
+++ binutils-2.17/binutils/wrstabs.c	2006-12-04 05:09:53.000000000 +0000
@@ -1869,7 +1869,7 @@
 {
   struct stab_write_handle *info = (struct stab_write_handle *) p;
   long index;
-  unsigned int size;
+  unsigned int size = 0;
 
   index = stab_get_struct_index (info, name, id, kind, &size);
   if (index < 0)
diff -Naur binutils-2.17.orig/gas/symbols.c binutils-2.17/gas/symbols.c
--- binutils-2.17.orig/gas/symbols.c	2006-01-09 17:14:40.000000000 +0000
+++ binutils-2.17/gas/symbols.c	2006-12-04 05:09:53.000000000 +0000
@@ -928,13 +928,11 @@
 	  && seg_right != undefined_section)
 	{
 	  if (right)
-	    as_bad_where (file, line,
-			  _("invalid sections for operation on `%s' and `%s' setting `%s'"),
-			  S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
+	    as_bad (_("invalid sections for operation on `%s' and `%s' setting `%s'"),
+		    S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
 	  else
-	    as_bad_where (file, line,
-			  _("invalid section for operation on `%s' setting `%s'"),
-			  S_GET_NAME (left), S_GET_NAME (symp));
+	    as_bad (_("invalid section for operation on `%s' setting `%s'"),
+		    S_GET_NAME (left), S_GET_NAME (symp));
 	}
     }
 }
diff -Naur binutils-2.17.orig/ld/ld.h binutils-2.17/ld/ld.h
--- binutils-2.17.orig/ld/ld.h	2005-09-30 11:42:04.000000000 +0000
+++ binutils-2.17/ld/ld.h	2006-12-04 05:09:53.000000000 +0000
@@ -1,6 +1,6 @@
 /* ld.h -- general linker header file
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005
+   2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GLD, the Gnu Linker.
@@ -282,6 +282,7 @@
 
 extern int yyparse (void);
 extern void add_cref (const char *, bfd *, asection *, bfd_vma);
+extern bfd_boolean handle_asneeded_cref (bfd *, enum notice_asneeded_action);
 extern void output_cref (FILE *);
 extern void check_nocrossrefs (void);
 extern void ld_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
diff -Naur binutils-2.17.orig/ld/ldcref.c binutils-2.17/ld/ldcref.c
--- binutils-2.17.orig/ld/ldcref.c	2006-03-16 12:20:16.000000000 +0000
+++ binutils-2.17/ld/ldcref.c	2006-12-04 05:09:53.000000000 +0000
@@ -27,6 +27,7 @@
 #include "sysdep.h"
 #include "bfdlink.h"
 #include "libiberty.h"
+#include "objalloc.h"
 
 #include "ld.h"
 #include "ldmain.h"
@@ -101,6 +102,15 @@
 
 static size_t cref_symcount;
 
+/* Used to take a snapshot of the cref hash table when starting to
+   add syms from an as-needed library.  */
+static struct bfd_hash_entry **old_table;
+static unsigned int old_size;
+static void *old_tab;
+static void *alloc_mark;
+static size_t tabsize, entsize, refsize;
+static size_t old_symcount;
+
 /* Create an entry in a cref hash table.  */
 
 static struct bfd_hash_entry *
@@ -165,7 +175,9 @@
 
   if (r == NULL)
     {
-      r = xmalloc (sizeof *r);
+      r = bfd_hash_allocate (&cref_table.root, sizeof *r);
+      if (r == NULL)
+	einfo (_("%X%P: cref alloc failed: %E\n"));
       r->next = h->refs;
       h->refs = r;
       r->abfd = abfd;
@@ -182,6 +194,123 @@
     r->def = TRUE;
 }
 
+/* Called before loading an as-needed library to take a snapshot of
+   the cref hash table, and after we have loaded or found that the
+   library was not needed.  */
+
+bfd_boolean
+handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
+		      enum notice_asneeded_action act)
+{
+  unsigned int i;
+
+  if (!cref_initialized)
+    return TRUE;
+
+  if (act == notice_as_needed)
+    {
+      char *old_ent, *old_ref;
+
+      for (i = 0; i < cref_table.root.size; i++)
+	{
+	  struct bfd_hash_entry *p;
+	  struct cref_hash_entry *c;
+	  struct cref_ref *r;
+
+	  for (p = cref_table.root.table[i]; p != NULL; p = p->next)
+	    {
+	      entsize += cref_table.root.entsize;
+	      c = (struct cref_hash_entry *) p;
+	      for (r = c->refs; r != NULL; r = r->next)
+		refsize += sizeof (struct cref_hash_entry);
+	    }
+	}
+
+      tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
+      old_tab = xmalloc (tabsize + entsize + refsize);
+
+      alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
+      if (alloc_mark == NULL)
+	return FALSE;
+
+      memcpy (old_tab, cref_table.root.table, tabsize);
+      old_ent = (char *) old_tab + tabsize;
+      old_ref = (char *) old_ent + entsize;
+      old_table = cref_table.root.table;
+      old_size = cref_table.root.size;
+      old_symcount = cref_symcount;
+
+      for (i = 0; i < cref_table.root.size; i++)
+	{
+	  struct bfd_hash_entry *p;
+	  struct cref_hash_entry *c;
+	  struct cref_ref *r;
+
+	  for (p = cref_table.root.table[i]; p != NULL; p = p->next)
+	    {
+	      memcpy (old_ent, p, cref_table.root.entsize);
+	      old_ent = (char *) old_ent + cref_table.root.entsize;
+	      c = (struct cref_hash_entry *) p;
+	      for (r = c->refs; r != NULL; r = r->next)
+		{
+		  memcpy (old_ref, r, sizeof (struct cref_hash_entry));
+		  old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
+		}
+	    }
+	}
+      return TRUE;
+    }
+
+  if (act == notice_not_needed)
+    {
+      char *old_ent, *old_ref;
+
+      if (old_tab == NULL)
+	{
+	  /* The only way old_tab can be NULL is if the cref hash table
+	     had not been initialised when notice_as_needed.  */
+	  bfd_hash_table_free (&cref_table.root);
+	  cref_initialized = FALSE;
+	  return TRUE;
+	}
+
+      old_ent = (char *) old_tab + tabsize;
+      old_ref = (char *) old_ent + entsize;
+      cref_table.root.table = old_table;
+      cref_table.root.size = old_size;
+      memcpy (cref_table.root.table, old_tab, tabsize);
+      cref_symcount = old_symcount;
+
+      for (i = 0; i < cref_table.root.size; i++)
+	{
+	  struct bfd_hash_entry *p;
+	  struct cref_hash_entry *c;
+	  struct cref_ref *r;
+
+	  for (p = cref_table.root.table[i]; p != NULL; p = p->next)
+	    {
+	      memcpy (p, old_ent, cref_table.root.entsize);
+	      old_ent = (char *) old_ent + cref_table.root.entsize;
+	      c = (struct cref_hash_entry *) p;
+	      for (r = c->refs; r != NULL; r = r->next)
+		{
+		  memcpy (r, old_ref, sizeof (struct cref_hash_entry));
+		  old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
+		}
+	    }
+	}
+
+      objalloc_free_block ((struct objalloc *) cref_table.root.memory,
+			   alloc_mark);
+    }
+  else if (act != notice_needed)
+    return FALSE;
+
+  free (old_tab);
+  old_tab = NULL;
+  return TRUE;
+}
+
 /* Copy the addresses of the hash table entries into an array.  This
    is called via cref_hash_traverse.  We also fill in the demangled
    name.  */
diff -Naur binutils-2.17.orig/ld/ldlang.c binutils-2.17/ld/ldlang.c
--- binutils-2.17.orig/ld/ldlang.c	2006-06-12 13:05:04.000000000 +0000
+++ binutils-2.17/ld/ldlang.c	2006-12-04 05:09:53.000000000 +0000
@@ -4207,7 +4207,8 @@
 		    /* If a loadable section is using the default memory
 		       region, and some non default memory regions were
 		       defined, issue an error message.  */
-		    if (!IGNORE_SECTION (os->bfd_section)
+		    if (!os->ignored
+			&& !IGNORE_SECTION (os->bfd_section)
 			&& ! link_info.relocatable
 			&& check_regions
 			&& strcmp (os->region->name,
diff -Naur binutils-2.17.orig/ld/ldmain.c binutils-2.17/ld/ldmain.c
--- binutils-2.17.orig/ld/ldmain.c	2006-04-06 18:52:45.000000000 +0000
+++ binutils-2.17/ld/ldmain.c	2006-12-04 05:09:53.000000000 +0000
@@ -1511,6 +1511,13 @@
 	asection *section,
 	bfd_vma value)
 {
+  if (name == NULL)
+    {
+      if (command_line.cref || nocrossref_list != NULL)
+	return handle_asneeded_cref (abfd, value);
+      return TRUE;
+    }
+
   if (! info->notice_all
       || (info->notice_hash != NULL
 	  && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
diff -Naur binutils-2.17.orig/ld/testsuite/ld-m68k/m68k.exp binutils-2.17/ld/testsuite/ld-m68k/m68k.exp
--- binutils-2.17.orig/ld/testsuite/ld-m68k/m68k.exp	2006-03-25 10:24:27.000000000 +0000
+++ binutils-2.17/ld/testsuite/ld-m68k/m68k.exp	2006-12-04 05:09:53.000000000 +0000
@@ -53,3 +53,4 @@
 run_dump_test "merge-error-1e"
 run_dump_test "merge-ok-1a"
 run_dump_test "merge-ok-1b"
+run_dump_test "merge-ok-1c"
diff -Naur binutils-2.17.orig/ld/testsuite/ld-m68k/merge-ok-1c.d binutils-2.17/ld/testsuite/ld-m68k/merge-ok-1c.d
--- binutils-2.17.orig/ld/testsuite/ld-m68k/merge-ok-1c.d	1970-01-01 00:00:00.000000000 +0000
+++ binutils-2.17/ld/testsuite/ld-m68k/merge-ok-1c.d	2006-12-04 05:09:53.000000000 +0000
@@ -0,0 +1,6 @@
+#source: merge-error-1a.s -march=cpu32
+#source: merge-error-1b.s -march=cpu32
+#ld: -r
+#objdump: -p
+#...
+private flags = 810000: \[cpu32\]
diff -Naur binutils-2.17.orig/ld/testsuite/ld-scripts/empty-orphan.d binutils-2.17/ld/testsuite/ld-scripts/empty-orphan.d
--- binutils-2.17.orig/ld/testsuite/ld-scripts/empty-orphan.d	2005-03-17 16:20:39.000000000 +0000
+++ binutils-2.17/ld/testsuite/ld-scripts/empty-orphan.d	2006-12-04 05:09:53.000000000 +0000
@@ -1,3 +1,6 @@
 #source: empty-orphan.s
 #ld: -T empty-orphan.t
-#error: no memory region specified for loadable section
+#readelf: -l --wide
+#...
+ +LOAD +[x0-9a-f]+ [x0]+70000000 [x0]+70000000 [x0]+(2|4|8|10|20|40|80) .*
+#pass
diff -Naur binutils-2.17.orig/ld/testsuite/ld-scripts/empty-orphan.t binutils-2.17/ld/testsuite/ld-scripts/empty-orphan.t
--- binutils-2.17.orig/ld/testsuite/ld-scripts/empty-orphan.t	2005-03-17 16:20:39.000000000 +0000
+++ binutils-2.17/ld/testsuite/ld-scripts/empty-orphan.t	2006-12-04 05:09:53.000000000 +0000
@@ -17,5 +17,6 @@
    .text : { *(.text) } > text_mem : text_phdr
    .data : { *(.data) } > data_mem : data_phdr
    .bss : { *(.bss) } > data_mem : data_phdr
+   /DISCARD/ : { *(.reginfo) }
    /* .orphan_data is an orphan */
 }
