]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add a do_assignments hook to ldemul
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 28 Apr 2016 12:25:17 +0000 (05:25 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 3 May 2016 17:37:16 +0000 (10:37 -0700)
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 in lang_do_assignments just before the call to
lang_do_assignments_1.

bfd/

* elf-bfd.h (_bfd_elf_record_start_stop): New prototype.
* elflink.c (start_stop_symbol): New struct.
(start_stop_symbol_info): Likewise.
(elf_link_collect_start_stop): New function.
(_bfd_elf_record_start_stop): Likewise.

ld/

* ldemul.c (ldemul_do_assignments): New function.
* ldemul.h (ldemul_do_assignments): New prototype.
(ld_emulation_xfer_struct): Add do_assignments.
* ldlang.c (lang_do_assignments): Call ldemul_do_assignments
just before lang_do_assignments_1 in lang_mark_phase_enum.
* emultempl/aix.em (ld_${EMULATION_NAME}_emulation): Initialize
the do_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}_do_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 do_assignments
field with gld${EMULATION_NAME}_do_assignments by default.

21 files changed:
bfd/elf-bfd.h
bfd/elflink.c
ld/emultempl/aix.em
ld/emultempl/armcoff.em
ld/emultempl/beos.em
ld/emultempl/elf32.em
ld/emultempl/generic.em
ld/emultempl/gld960.em
ld/emultempl/gld960c.em
ld/emultempl/linux.em
ld/emultempl/lnk960.em
ld/emultempl/m68kcoff.em
ld/emultempl/msp430.em
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/emultempl/sunos.em
ld/emultempl/ticoff.em
ld/emultempl/vanilla.em
ld/ldemul.c
ld/ldemul.h
ld/ldlang.c

index 9067dd9aea174739300af7b8076b558267e27b94..2dafbcf6a7a5a752f70c85c3ecd371f646b55ec1 100644 (file)
@@ -2341,6 +2341,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 *);
 
index b6ff6b650a96e897de5ac771175625fae584fbc8..a6e5bfb4818f451103a37fdcc004493fca706ab1 100644 (file)
@@ -13791,3 +13791,130 @@ 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);
 }
+
+/* A linked list of __start_<name> and __stop_<name> symbols  */
+
+struct start_stop_symbol
+{
+  struct elf_link_hash_entry *h;
+  const char *sec_name;
+  struct start_stop_symbol *next;
+};
+
+struct start_stop_symbol_info
+{
+  struct start_stop_symbol *symbol_list;
+  bfd_boolean failed;
+};
+
+/* Collect __start_<name> and __stop_<name> symbols referenced by
+   regular objects.  This is called via elf_link_hash_traverse.  */
+
+static bfd_boolean
+elf_link_collect_start_stop (struct elf_link_hash_entry *h, void *data)
+{
+  if (!h->def_regular && h->ref_regular)
+    {
+      struct start_stop_symbol_info *info;
+      struct start_stop_symbol *p, **head;
+      const char *sec_name = h->root.root.string;
+
+      if (sec_name[0] == '_'
+         && sec_name[1] == '_'
+         && sec_name[2] == 's'
+         && sec_name[3] == 't')
+       sec_name += 4;
+      else
+       return TRUE;
+
+      if (sec_name[0] == 'a'
+         && sec_name[1] == 'r'
+         && sec_name[2] == 't')
+       sec_name += 3;
+      else if (sec_name[0] == 'o'
+              && sec_name[1] == 'p')
+       sec_name += 2;
+      else
+       return TRUE;
+
+      if (sec_name[0] == '_' && sec_name[1] != '\0')
+       sec_name += 1;
+      else
+       return TRUE;
+
+      info = (struct start_stop_symbol_info *) data;
+
+      p = (struct start_stop_symbol *) bfd_malloc (sizeof (*p));
+      if (p == NULL)
+       {
+         info->failed = TRUE;
+         return FALSE;
+       }
+
+      head = &info->symbol_list;
+      p->next = info->symbol_list;
+      p->h = h;
+      p->sec_name = sec_name;
+      *head = p;
+    }
+  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)
+{
+  struct start_stop_symbol_info symbols;
+
+  /* Collect start/stop symbols.  Assuming there are fewer start/stop
+     symbols than input files, avoid scan over all input files for each
+     start/stop symbol.  */
+  symbols.symbol_list = NULL;
+  symbols.failed = FALSE;
+  elf_link_hash_traverse (elf_hash_table (info),
+                         elf_link_collect_start_stop, &symbols);
+
+  if (symbols.failed)
+    info->callbacks->einfo (_("%P%X: collect start/stop symbols: %E\n"));
+  else if (symbols.symbol_list)
+    {
+      bfd *i;
+
+      for (i = info->input_bfds; i != NULL; i = i->link.next)
+       if ((i->flags
+            & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+         {
+           /* Only check regular input files.  */
+           struct start_stop_symbol *p, **pp;
+
+           for (pp = &symbols.symbol_list; (p = *pp) != NULL; )
+             if (bfd_get_section_by_name (i, p->sec_name) != NULL)
+               {
+                 p->h->def_regular = 1;
+                 p->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 (p->h->def_dynamic)
+                   {
+                     p->h->root.type = bfd_link_hash_undefined;
+                     p->h->root.u.undef.abfd
+                       = p->h->root.u.def.section->owner;
+                   }
+
+                 /* Remove this from the list.  */
+                 *pp = p->next;
+                 free (p);
+               }
+             else
+               pp = &p->next;
+
+           /* Stop when the list is empty.  */
+           if (symbols.symbol_list == NULL)
+             break;
+         }
+    }
+}
index b9cab4e691cafbaaa95f74cc455fbe4bc601cd8d..3c775f93f385ba9d04cb93dbe3b163e450c9b56b 100644 (file)
@@ -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                         /* do_assignments */
 };
 EOF
index 387a1f71f44a9dd0092e9665ba98a3aaefb2b42a..98489955e2edb501ee063add0476ce407de1b277 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 64301023394e33aa45bc7745d56be348ecab5076..26226887ca8b57ed1c11d11d80fe95b36344e1d2 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 4f5d1a4d2c029c521c31739fc86a4836fa8be014..1b26e1f7c4d00a84e62382fc24b84c056e5b7ede 100644 (file)
@@ -1330,6 +1330,7 @@ fragment <<EOF
 EOF
 fi
 
+if test x"$LDEMUL_DO_ASSIGNMENTS" != xgld"$EMULATION_NAME"_do_assignments; then
 fragment <<EOF
 
 /* Look through an expression for an assignment statement.  */
@@ -1398,7 +1399,83 @@ 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}_do_assignments (void)
+{
+  if (is_elf_hash_table (link_info.hash))
+    {
+      /* 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);
+
+      /* 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.  def_regular is
+            set by the ELF backend if __ehdr_start is defined in linker
+            script.  */
+         if (h != NULL
+             && !h->def_regular
+             && (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;
+           }
+       }
+    }
+}
+
+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 +1532,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 +1541,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 +1653,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 +2547,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_DO_ASSIGNMENTS-gld${EMULATION_NAME}_do_assignments},
 };
 EOF
index 7924cdf21aa46e2d2bb1fbdb0dd2e692ef2c4e50..66e35f73cefea2a7958cf82b2351d5d3408635a1 100644 (file)
@@ -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_DO_ASSIGNMENTS-NULL}
 };
 EOF
index c4c9c5586587344291cde409848cd30fd3c2b98b..0281969554e76b367b38bcbb83d42f55f3fda3c7 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 6b80be2ac4bdcc7784cf96f49a497676ae9b812b..3fede68855b1122adb1dca4bacc85aa86df1747c 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index c28e9785b466366873028291f6474c6523c717ca..da8d9a9e15f1ad49c17041f18aa2cdc8435536df 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 4a2bd72f59ea0acb4f07be8f65b6193abb5f372a..ef345afb02eea6ca3804c5593e8d9eb75ebb12e6 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 594cd56d6a4fa37763292ef78f8b9e65f2b2bcf3..a6c7fdacc1020ecf9b7bf76b0c99116255aad3c3 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 22e7c42b11736bd2a930dda0357f8271307dd313..081018112c4b0cba88ce769e0a3c2e9907bb3b0d 100644 (file)
@@ -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_DO_ASSIGNMENTS-NULL}
 };
 EOF
 # \f
index c13fa4d1a2c9d4f003223c04a597d332e697c582..f67a701d925f34be41b189e91bcdae365c1a7472 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index ab7c473439a0cddf95e6ef2ca210759454348890..33fd95d56c90b406f7204b1a246423a98ac4d8ff 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 8be8669a3b8560a90d3f912d8d8d59da188f3927..a019d6f807cac7feab1526ea6da9cf7e9b4130ea 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 9b5495e7c4ae0d3d15a35566d4a228364d3e0c19..eb9d3e7c58e4e4cf000e42baeceeff170ac1a8c8 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index d627dfc6f78b9a4e0988d9af1e06e6bdca5c9787..b986ae90b7272d2d54bbd9e7af86875e7c94eb35 100644 (file)
@@ -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 /* do_assignments */
 };
 EOF
index 841a14d51aca012b704acc0b50de4048663e4c95..c2532cbbd7881e3e30d23e88cecd9a0c1e35fed5 100644 (file)
@@ -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_do_assignments (void)
+{
+  if (ld_emulation->do_assignments)
+    ld_emulation->do_assignments ();
+}
index 937b1c990279f39f5357b5f88146fe2bc19a2dc1..cbc63551136b1938eaa81be756576d28ec1b1eee 100644 (file)
@@ -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_do_assignments
+  (void);
 
 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 do assignments.  */
+  void (*do_assignments)
+    (void);
+
 } ld_emulation_xfer_type;
 
 typedef enum {
index 96947da974ba920ee44e5023535ba69962b285a5..53d61921bd149664554c1bd931de8ddd395537f6 100644 (file)
@@ -5760,6 +5760,8 @@ lang_do_assignments (lang_phase_type phase)
   prefer_next_section = FALSE;
   expld.phase = phase;
   lang_statement_iteration++;
+  if (phase == lang_mark_phase_enum)
+    ldemul_do_assignments ();
   lang_do_assignments_1 (statement_list.head,
                         abs_output_section, NULL, 0, &found_end);
 }