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]

[PATCH] Add a record_link_assignments hook to ldemul


On Thu, Apr 28, 2016 at 10:11 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Apr 28, 2016 at 6:40 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Thu, Apr 28, 2016 at 6:09 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Thu, Apr 28, 2016 at 6:07 AM, Alan Modra <amodra@gmail.com> wrote:
>>>> On Thu, Apr 28, 2016 at 05:49:57AM -0700, H.J. Lu wrote:
>>>>> On Wed, Apr 27, 2016 at 6:11 PM, Alan Modra <amodra@gmail.com> wrote:
>>>>> > On Wed, Apr 27, 2016 at 03:24:48PM -0700, H.J. Lu wrote:
>>>>> >> bfd_elf_record_link_assignment
>>>>> >> is called after check_relocs.  bfd_elf_record_link_assignment sets non_elf,
>>>>> >> def_regular and  forced_local.   For PROVIDE, it also updates root.type. They
>>>>> >> are needed in reloc_checks.
>>>>> >
>>>>> > My guess is that symbol twiddling done in before_allocation should be
>>>>> > moved to a new ldemul hook called at the start of lang_do_assignments.
>>>>> > The idea being to stabilize symbols earlier.
>>>>> >
>>>>> > The hook would twiddle __ehdr_start and call find_statement_assignment
>>>>> > when lang_mark_phase_enum.  Reversing the __ehdr_start twiddle stays
>>>>> > in before_allocation.
>>>>> >
>>>>>
>>>>> I tried this.  But it doesn't work with __start/__stop symbols.  I
>>>>> need to know if they are defined and referenced local in check_relocs.
>>>> [snip]
>>>>
>>>>> --- a/ld/ldlang.c
>>>>> +++ b/ld/ldlang.c
>>>>> @@ -6930,6 +6930,8 @@ lang_process (void)
>>>>>       collection in order to make sure that all symbol aliases are resolved.  */
>>>>>    lang_do_assignments (lang_mark_phase_enum);
>>>>>
>>>>> +  ldemul_record_link_assignments (lang_mark_phase_enum);
>>>>> +
>>>>>    lang_do_memory_regions();
>>>>>    expld.phase = lang_first_phase_enum;
>>>>
>>>> You'll need to run ldemul_record_link_assignments before
>>>> lang_do_assignments if you want provided symbols to be defined.
>>>
>>> I got many more failures when I did that since many assignments
>>> haven't been processed yet.
>>>
>>>> I suggest renaming to ldemul_do_assignments and putting
>>>>   ldemul_do_assignments (phase);
>>>> inside lang_do_assignments just before the call to
>>>> lang_do_assignments_1.
>>>>
>>
>> With this patch, I only got 2 failures on x86-64.
>>
>
> This one works for both i386 and x86-64.
>

This is the complete patch.  OK for master?


-- 
H.J.
From e34bcbafec5ec5181440d4abe9a4f43ca5eb50c8 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 28 Apr 2016 05:25:17 -0700
Subject: [PATCH] Add a record_link_assignments hook to ldemul

When ELF relocation check is moved after lang_gc_sections, we should
call bfd_elf_record_link_assignment before ELF relocation check so that
linker defined symbols will be processed earlier to stabilize symbols.
We have to do it after lang_do_assignments to make sure that assignments
in linker scripts are processed first before updating fields in
elf_link_hash_entry.

bfd/

	* elf-bfd.h (_bfd_elf_record_start_stop): New prototype.
	* elflink.c (_bfd_elf_is_start_stop): Updated to check symbols
	currently defined in dynamic objects.
	(elf_link_record_start_stop): New function.
	(_bfd_elf_record_start_stop): Likewise.

ld/

	* ldemul.c (ldemul_record_link_assignments): New function.
	* ldemul.h (ldemul_record_link_assignments): New prototype.
	(ld_emulation_xfer_struct): Add record_link_assignments.
	* ldlang.c (lang_process): Call ldemul_record_link_assignments
	after lang_do_assignments.
	* emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Initialize
	the record_link_assignments field to NULL.
	* emultempl/armcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/beos.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/generic.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/gld960.em (ld_gld960_emulation): Likewise.
	* emultempl/gld960c.em (ld_gld960coff_emulation): Likewise.
	* emultempl/linux.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/lnk960.em (ld_lnk960_emulation): Likewise.
	* emultempl/m68kcoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/msp430.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/pe.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/pep.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/sunos.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/ticoff.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/vanilla.em (ld_${EMULATION_NAME}_emulation): Likewise.
	* emultempl/elf32.em (ehdr_start): New variable.
	(ehdr_start_save): Likewise.
	(gld${EMULATION_NAME}_record_link_assignments): New function.
	(gld${EMULATION_NAME}_restore_ehdr_start): Likewise.
	(ehdr_start_empty): Removed.
	(gld${EMULATION_NAME}_before_allocation): Don't adjust
	__ehdr_start here.  Call gld${EMULATION_NAME}_restore_ehdr_start
	at the end.
	(ld_${EMULATION_NAME}_emulation): Initialize
	the record_link_assignments field with
	gld${EMULATION_NAME}_record_link_assignments by default.
---
 bfd/elf-bfd.h            |   3 +
 bfd/elflink.c            |  87 ++++++++++++++++++++++-------
 ld/emultempl/aix.em      |   3 +-
 ld/emultempl/armcoff.em  |   3 +-
 ld/emultempl/beos.em     |   3 +-
 ld/emultempl/elf32.em    | 139 +++++++++++++++++++++++++++--------------------
 ld/emultempl/generic.em  |   3 +-
 ld/emultempl/gld960.em   |   3 +-
 ld/emultempl/gld960c.em  |   3 +-
 ld/emultempl/linux.em    |   3 +-
 ld/emultempl/lnk960.em   |   3 +-
 ld/emultempl/m68kcoff.em |   3 +-
 ld/emultempl/msp430.em   |   3 +-
 ld/emultempl/pe.em       |   3 +-
 ld/emultempl/pep.em      |   3 +-
 ld/emultempl/sunos.em    |   3 +-
 ld/emultempl/ticoff.em   |   3 +-
 ld/emultempl/vanilla.em  |   3 +-
 ld/ldemul.c              |   7 +++
 ld/ldemul.h              |   6 ++
 ld/ldlang.c              |   3 +
 21 files changed, 196 insertions(+), 94 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 6c05b55..49dc70b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2339,6 +2339,9 @@ extern bfd_boolean bfd_elf_gc_common_final_link
 extern asection *_bfd_elf_is_start_stop
   (const struct bfd_link_info *, struct elf_link_hash_entry *);
 
+extern void _bfd_elf_record_start_stop
+  (struct bfd_link_info *);
+
 extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
   (bfd_vma, void *);
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index b6ff6b6..9395052 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12230,8 +12230,9 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
-/* For undefined __start_<name> and __stop_<name> symbols, return the
-   first input section matching <name>.  Return NULL otherwise.  */
+/* For __start_<name> and __stop_<name> symbols, return the first
+   input section matching <name> in a regular object.  Return NULL
+   otherwise.  */
 
 asection *
 _bfd_elf_is_start_stop (const struct bfd_link_info *info,
@@ -12239,17 +12240,28 @@ _bfd_elf_is_start_stop (const struct bfd_link_info *info,
 {
   asection *s;
   const char *sec_name;
+  bfd_boolean undefined = (h->root.type == bfd_link_hash_undefined
+			   || h->root.type == bfd_link_hash_undefweak);
 
-  if (h->root.type != bfd_link_hash_undefined
-      && h->root.type != bfd_link_hash_undefweak)
-    return NULL;
-
-  s = h->root.u.undef.section;
-  if (s != NULL)
+  if (undefined)
+    {
+      s = h->root.u.undef.section;
+      if (s != NULL)
+	{
+	  if (s == (asection *) 0 - 1)
+	    return NULL;
+	  return s;
+	}
+    }
+  else
     {
-      if (s == (asection *) 0 - 1)
+      /* Symbol is defined.  Check if it is also defined in a regular
+	 input file only when it is currently defined in a dynamic
+	 object, since otherwise, it can't be a __start_<name> nor
+	 __stop_<name> symbol.  */
+      if (!h->def_dynamic)
 	return NULL;
-      return s;
+      s = NULL;
     }
 
   sec_name = NULL;
@@ -12262,18 +12274,21 @@ _bfd_elf_is_start_stop (const struct bfd_link_info *info,
     {
       bfd *i;
 
+      /* Only check regular input files.  */
       for (i = info->input_bfds; i != NULL; i = i->link.next)
-	{
-	  s = bfd_get_section_by_name (i, sec_name);
-	  if (s != NULL)
-	    {
-	      h->root.u.undef.section = s;
-	      break;
-	    }
-	}
+	if ((i->flags
+	     & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+	  {
+	    s = bfd_get_section_by_name (i, sec_name);
+	    if (s != NULL)
+	      {
+		h->root.u.undef.section = s;
+		break;
+	      }
+	  }
     }
 
-  if (s == NULL)
+  if (undefined && s == NULL)
     h->root.u.undef.section = (asection *) 0 - 1;
 
   return s;
@@ -13791,3 +13806,37 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
   bed->s->swap_reloc_out (abfd, rel, loc);
 }
+
+/* Record __start_<name> and __stop_<name> symbols referenced by
+   regular objects.  This is called via elf_link_hash_traverse.  */
+
+static bfd_boolean
+elf_link_record_start_stop (struct elf_link_hash_entry *h, void *data)
+{
+  if (!h->def_regular && h->ref_regular)
+    {
+      asection *sec
+	= _bfd_elf_is_start_stop ((struct bfd_link_info *) data, h);
+      if (sec != NULL)
+	{
+	  h->def_regular = 1;
+	  h->type = STT_OBJECT;
+	  /* If it is currently defined by a dynamic object, but not
+	     by a regular object, then mark it as undefined so that
+	     the generic linker will force the correct value.  */
+	  if (h->def_dynamic)
+	    h->root.type = bfd_link_hash_undefined;
+	}
+    }
+  return TRUE;
+}
+
+/* Record all __start_<name> and __stop_<name> symbols referenced by
+   regular objects.  */
+
+void
+_bfd_elf_record_start_stop (struct bfd_link_info * info)
+{
+  elf_link_hash_traverse (elf_hash_table (info),
+			  elf_link_record_start_stop, info);
+}
diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em
index b9cab4e..b625c44 100644
--- a/ld/emultempl/aix.em
+++ b/ld/emultempl/aix.em
@@ -1554,6 +1554,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   NULL,				/* recognized_file */
   NULL,				/* find potential_libraries */
   NULL,				/* new_vers_pattern */
-  NULL				/* extra_map_file_text */
+  NULL,				/* extra_map_file_text */
+  NULL				/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em
index 387a1f7..adfaa1e 100644
--- a/ld/emultempl/armcoff.em
+++ b/ld/emultempl/armcoff.em
@@ -280,6 +280,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em
index 6430102..8f861a8 100644
--- a/ld/emultempl/beos.em
+++ b/ld/emultempl/beos.em
@@ -778,6 +778,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 4f5d1a4..bb73dff 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1330,6 +1330,7 @@ fragment <<EOF
 EOF
 fi
 
+if test x"$LDEMUL_RECORD_LINK_ASSIGNMENTS" != xgld"$EMULATION_NAME"_record_link_assignments; then
 fragment <<EOF
 
 /* Look through an expression for an assignment statement.  */
@@ -1398,7 +1399,81 @@ gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
     gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
 }
 
+static struct elf_link_hash_entry *ehdr_start;
+static struct bfd_link_hash_entry ehdr_start_save;
+
+static void
+gld${EMULATION_NAME}_record_link_assignments (lang_phase_type phase)
+{
+  if (phase == lang_mark_phase_enum
+      && is_elf_hash_table (link_info.hash))
+    {
+      /* Make __ehdr_start hidden if it has been referenced, to
+	 prevent the symbol from being dynamic.  */
+      if (!bfd_link_relocatable (&link_info))
+	{
+	  struct elf_link_hash_entry *h
+	    = elf_link_hash_lookup (elf_hash_table (&link_info),
+				    "__ehdr_start", FALSE, FALSE, TRUE);
+
+	  /* Only adjust the export class if the symbol was referenced
+	     and not defined, otherwise leave it alone.  */
+	  if (h != NULL
+	      && (h->root.type == bfd_link_hash_new
+		  || h->root.type == bfd_link_hash_undefined
+		  || h->root.type == bfd_link_hash_undefweak
+		  || h->root.type == bfd_link_hash_common))
+	    {
+	      _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+	      if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+	      /* Don't leave the symbol undefined.  Undefined hidden
+		 symbols typically won't have dynamic relocations, but
+		 we most likely will need dynamic relocations for
+		 __ehdr_start if we are building a PIE or shared
+		 library.  */
+	      ehdr_start = h;
+	      ehdr_start_save = h->root;
+	      h->root.type = bfd_link_hash_defined;
+	      h->root.u.def.section = bfd_abs_section_ptr;
+	      h->root.u.def.value = 0;
+	    }
+	}
+
+      /* If we are going to make any variable assignments, we need to
+	 let the ELF backend know about them in case the variables are
+	 referred to by dynamic objects.  */
+      lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
+
+      /* Also let the ELF backend know about __start_<name> and
+	 __stop_<name> symbols.  */
+      _bfd_elf_record_start_stop (&link_info);
+    }
+}
+
+static void
+gld${EMULATION_NAME}_restore_ehdr_start (void)
+{
+  if (ehdr_start != NULL)
+    {
+      /* If we twiddled __ehdr_start to defined earlier, put it back
+	 as it was.  */
+      ehdr_start->root.type = ehdr_start_save.type;
+      ehdr_start->root.u = ehdr_start_save.u;
+    }
+}
+
 EOF
+else
+fragment <<EOF
+
+static
+gld${EMULATION_NAME}_restore_ehdr_start (void)
+{
+}
+
+EOF
+fi
 
 if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
   if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
@@ -1455,11 +1530,6 @@ gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
     }
 }
 
-#if defined(__GNUC__) && GCC_VERSION < 4006
-  /* Work around a GCC uninitialized warning bug fixed in GCC 4.6.  */
-static struct bfd_link_hash_entry ehdr_start_empty;
-#endif
-
 /* This is called after the sections have been attached to output
    sections, but before any sizes or addresses have been set.  */
 
@@ -1469,55 +1539,9 @@ gld${EMULATION_NAME}_before_allocation (void)
   const char *rpath;
   asection *sinterp;
   bfd *abfd;
-  struct elf_link_hash_entry *ehdr_start = NULL;
-#if defined(__GNUC__) && GCC_VERSION < 4006
-  /* Work around a GCC uninitialized warning bug fixed in GCC 4.6.  */
-  struct bfd_link_hash_entry ehdr_start_save = ehdr_start_empty;
-#else
-  struct bfd_link_hash_entry ehdr_start_save;
-#endif
 
   if (is_elf_hash_table (link_info.hash))
-    {
-      _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
-
-      /* Make __ehdr_start hidden if it has been referenced, to
-	 prevent the symbol from being dynamic.  */
-      if (!bfd_link_relocatable (&link_info))
-       {
-         struct elf_link_hash_entry *h
-           = elf_link_hash_lookup (elf_hash_table (&link_info), "__ehdr_start",
-                                   FALSE, FALSE, TRUE);
-
-         /* Only adjust the export class if the symbol was referenced
-            and not defined, otherwise leave it alone.  */
-         if (h != NULL
-             && (h->root.type == bfd_link_hash_new
-                 || h->root.type == bfd_link_hash_undefined
-                 || h->root.type == bfd_link_hash_undefweak
-                 || h->root.type == bfd_link_hash_common))
-           {
-             _bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
-             if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
-               h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
-	     /* Don't leave the symbol undefined.  Undefined hidden
-		symbols typically won't have dynamic relocations, but
-		we most likely will need dynamic relocations for
-		__ehdr_start if we are building a PIE or shared
-		library.  */
-	     ehdr_start = h;
-	     ehdr_start_save = h->root;
-	     h->root.type = bfd_link_hash_defined;
-	     h->root.u.def.section = bfd_abs_section_ptr;
-	     h->root.u.def.value = 0;
-           }
-       }
-
-      /* If we are going to make any variable assignments, we need to
-	 let the ELF backend know about them in case the variables are
-	 referred to by dynamic objects.  */
-      lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
-    }
+    _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
 
   /* Let the ELF backend work out the sizes of any sections required
      by dynamic linking.  */
@@ -1627,13 +1651,7 @@ ${ELF_INTERPRETER_SET_DEFAULT}
   if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info))
     einfo ("%P%F: failed to set dynamic section sizes: %E\n");
 
-  if (ehdr_start != NULL)
-    {
-      /* If we twiddled __ehdr_start to defined earlier, put it back
-	 as it was.  */
-      ehdr_start->root.type = ehdr_start_save.type;
-      ehdr_start->root.u = ehdr_start_save.u;
-    }
+  gld${EMULATION_NAME}_restore_ehdr_start ();
 }
 
 EOF
@@ -2527,6 +2545,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL},
-  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
+  ${LDEMUL_RECORD_LINK_ASSIGNMENTS-gld${EMULATION_NAME}_record_link_assignments},
 };
 EOF
diff --git a/ld/emultempl/generic.em b/ld/emultempl/generic.em
index 7924cdf..cfe2b94 100644
--- a/ld/emultempl/generic.em
+++ b/ld/emultempl/generic.em
@@ -156,6 +156,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_RECOGNIZED_FILE-NULL},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL},
-  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
+  ${LDEMUL_RECORD_LINK_ASSIGNMENTS-NULL}
 };
 EOF
diff --git a/ld/emultempl/gld960.em b/ld/emultempl/gld960.em
index c4c9c55..3b22d1b 100644
--- a/ld/emultempl/gld960.em
+++ b/ld/emultempl/gld960.em
@@ -149,6 +149,7 @@ struct ld_emulation_xfer_struct ld_gld960_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/gld960c.em b/ld/emultempl/gld960c.em
index 6b80be2..09b09e9 100644
--- a/ld/emultempl/gld960c.em
+++ b/ld/emultempl/gld960c.em
@@ -162,6 +162,7 @@ struct ld_emulation_xfer_struct ld_gld960coff_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/linux.em b/ld/emultempl/linux.em
index c28e978..cc68c23 100644
--- a/ld/emultempl/linux.em
+++ b/ld/emultempl/linux.em
@@ -206,6 +206,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/lnk960.em b/ld/emultempl/lnk960.em
index 4a2bd72..ea4e133 100644
--- a/ld/emultempl/lnk960.em
+++ b/ld/emultempl/lnk960.em
@@ -343,6 +343,7 @@ struct ld_emulation_xfer_struct ld_lnk960_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL, /* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/m68kcoff.em b/ld/emultempl/m68kcoff.em
index 594cd56..dd4af3a 100644
--- a/ld/emultempl/m68kcoff.em
+++ b/ld/emultempl/m68kcoff.em
@@ -240,6 +240,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em
index 22e7c42..41d5a48 100644
--- a/ld/emultempl/msp430.em
+++ b/ld/emultempl/msp430.em
@@ -295,7 +295,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   ${LDEMUL_RECOGNIZED_FILE-NULL},
   ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
   ${LDEMUL_NEW_VERS_PATTERN-NULL},
-  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
+  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
+  ${LDEMUL_RECORD_LINK_ASSIGNMENTS-NULL}
 };
 EOF
 # 
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index c13fa4d..9d63eac 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -2483,6 +2483,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_recognized_file,
   gld_${EMULATION_NAME}_find_potential_libraries,
   NULL,	/* new_vers_pattern.  */
-  NULL	/* extra_map_file_text.  */
+  NULL,	/* extra_map_file_text.  */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index ab7c473..62cfb32 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -2257,6 +2257,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld_${EMULATION_NAME}_recognized_file,
   gld_${EMULATION_NAME}_find_potential_libraries,
   NULL,	/* new_vers_pattern.  */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/sunos.em b/ld/emultempl/sunos.em
index 8be8669..3f6bb23 100644
--- a/ld/emultempl/sunos.em
+++ b/ld/emultempl/sunos.em
@@ -1036,6 +1036,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/ticoff.em b/ld/emultempl/ticoff.em
index 9b5495e..b596b8f 100644
--- a/ld/emultempl/ticoff.em
+++ b/ld/emultempl/ticoff.em
@@ -181,6 +181,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   NULL, /* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL  /* extra_map_file_text */
+  NULL, /* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/emultempl/vanilla.em b/ld/emultempl/vanilla.em
index d627dfc..e80189c 100644
--- a/ld/emultempl/vanilla.em
+++ b/ld/emultempl/vanilla.em
@@ -82,6 +82,7 @@ struct ld_emulation_xfer_struct ld_vanilla_emulation =
   NULL,	/* recognized file */
   NULL,	/* find_potential_libraries */
   NULL,	/* new_vers_pattern */
-  NULL	/* extra_map_file_text */
+  NULL,	/* extra_map_file_text */
+  NULL	/* record_link_assignments */
 };
 EOF
diff --git a/ld/ldemul.c b/ld/ldemul.c
index 841a14d..c1a75f1 100644
--- a/ld/ldemul.c
+++ b/ld/ldemul.c
@@ -355,3 +355,10 @@ ldemul_extra_map_file_text (bfd *abfd, struct bfd_link_info *info, FILE *mapf)
   if (ld_emulation->extra_map_file_text)
     ld_emulation->extra_map_file_text (abfd, info, mapf);
 }
+
+void
+ldemul_record_link_assignments (lang_phase_type phase)
+{
+  if (ld_emulation->record_link_assignments)
+    ld_emulation->record_link_assignments (phase);
+}
diff --git a/ld/ldemul.h b/ld/ldemul.h
index 937b1c9..7f823d7 100644
--- a/ld/ldemul.h
+++ b/ld/ldemul.h
@@ -96,6 +96,8 @@ extern struct bfd_elf_version_expr *ldemul_new_vers_pattern
   (struct bfd_elf_version_expr *);
 extern void ldemul_extra_map_file_text
   (bfd *, struct bfd_link_info *, FILE *);
+extern void ldemul_record_link_assignments
+  (lang_phase_type);
 
 typedef struct ld_emulation_xfer_struct {
   /* Run before parsing the command line and script file.
@@ -201,6 +203,10 @@ typedef struct ld_emulation_xfer_struct {
   void (*extra_map_file_text)
     (bfd *, struct bfd_link_info *, FILE *);
 
+  /* Called to record link assignments.  */
+  void (*record_link_assignments)
+    (lang_phase_type);
+
 } ld_emulation_xfer_type;
 
 typedef enum {
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 96947da..881d0a3 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -6930,6 +6930,9 @@ lang_process (void)
      collection in order to make sure that all symbol aliases are resolved.  */
   lang_do_assignments (lang_mark_phase_enum);
 
+  /* Record symbols created by linker and linker scripts.  */
+  ldemul_record_link_assignments (lang_mark_phase_enum);
+
   lang_do_memory_regions();
   expld.phase = lang_first_phase_enum;
 
-- 
2.5.5


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