* ldlang.h (lang_output_section_find): Define.
authorAlan Modra <amodra@gmail.com>
Sun, 7 Sep 2008 04:02:31 +0000 (04:02 +0000)
committerAlan Modra <amodra@gmail.com>
Sun, 7 Sep 2008 04:02:31 +0000 (04:02 +0000)
(lang_output_section_statement_lookup): Update prototype.
* ldlang.c (lang_output_section_find,
lang_output_section_statement_lookup_1): Merge into..
(lang_output_section_statement_lookup): ..here.  Update all callers.
(process_insert_statements): Set constraint negative
for output section statements we might be inserting.  Make error
fatal on not finding insertion section.
(lang_output_section_find): Rather than comparing
output_section_statement.constraint against -1, test whether
it is postive.
(lang_output_section_statement_lookup_1): Likewise.
(output_prev_sec_find, strip_excluded_output_sections): Likewise.
(lang_record_phdrs): Likewise.
* emultempl/elf32.em (output_rel_find): Likewise.
* NEWS: Mention INSERT.

ld/ChangeLog
ld/NEWS
ld/emultempl/elf32.em
ld/ldlang.c
ld/ldlang.h

index 8123c0a..2f49f6b 100644 (file)
@@ -1,3 +1,22 @@
+2008-09-07  Alan Modra  <amodra@bigpond.net.au>
+
+       * ldlang.h (lang_output_section_find): Define.
+       (lang_output_section_statement_lookup): Update prototype.
+       * ldlang.c (lang_output_section_find,
+       lang_output_section_statement_lookup_1): Merge into..
+       (lang_output_section_statement_lookup): ..here.  Update all callers.
+       (process_insert_statements): Set constraint negative
+       for output section statements we might be inserting.  Make error
+       fatal on not finding insertion section.
+       (lang_output_section_find): Rather than comparing
+       output_section_statement.constraint against -1, test whether
+       it is postive.
+       (lang_output_section_statement_lookup_1): Likewise.
+       (output_prev_sec_find, strip_excluded_output_sections): Likewise.
+       (lang_record_phdrs): Likewise.
+       * emultempl/elf32.em (output_rel_find): Likewise.
+       * NEWS: Mention INSERT.
+
 2008-08-26  Nick Clifton  <nickc@redhat.com>
 
        PR 6727
diff --git a/ld/NEWS b/ld/NEWS
index c7648a0..13eac98 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,6 +1,9 @@
 -*- text -*-
+* Linker scripts support a new INSERT command that makes it easier to
+  augment the default script.
+
 * Linker script input section filespecs may now specify a file within an
- archive by writing "archive:file".
 archive by writing "archive:file".
 
 * The --sort-common switch now has an optional argument which specifies the
   direction of sorting.
@@ -8,9 +11,9 @@
 * The M68K linker now supports multiple GOT generation schemes controlled via
   the --got=<type> command line option.
 
-* The ARM EABI linker will now generate stubs for function calls to symbols that
-  are too far away.  The placement of the stubs is controlled by a new linker
-  command line option: --stub-group-size=N.
+* The ARM EABI linker will now generate stubs for function calls to symbols
+  that are too far away.  The placement of the stubs is controlled by a new
+  linker command line option: --stub-group-size=N.
 
 Changes in 2.18:
 
index 955fc9f..be9d78d 100644 (file)
@@ -1583,7 +1583,7 @@ output_rel_find (asection *sec, int isdyn)
        lookup != NULL;
        lookup = lookup->next)
     {
-      if (lookup->constraint != -1
+      if (lookup->constraint >= 0
          && CONST_STRNEQ (lookup->name, ".rel"))
        {
          int lookrela = lookup->name[4] == 'a';
index 8d95254..b1b8806 100644 (file)
@@ -1149,7 +1149,7 @@ lang_init (void)
   first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
                                    NULL);
   abs_output_section =
-    lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
+    lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE);
 
   abs_output_section->bfd_section = bfd_abs_section_ptr;
 
@@ -1255,44 +1255,19 @@ lang_memory_default (asection *section)
 }
 
 lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
+lang_output_section_statement_lookup (const char *const name,
+                                     int constraint,
+                                     bfd_boolean create)
 {
   struct out_section_hash_entry *entry;
-  unsigned long hash;
 
   entry = ((struct out_section_hash_entry *)
           bfd_hash_lookup (&output_section_statement_table, name,
-                           FALSE, FALSE));
+                           create, FALSE));
   if (entry == NULL)
-    return NULL;
-
-  hash = entry->root.hash;
-  do
     {
-      if (entry->s.output_section_statement.constraint != -1)
-       return &entry->s.output_section_statement;
-      entry = (struct out_section_hash_entry *) entry->root.next;
-    }
-  while (entry != NULL
-        && entry->root.hash == hash
-        && strcmp (name, entry->s.output_section_statement.name) == 0);
-
-  return NULL;
-}
-
-static lang_output_section_statement_type *
-lang_output_section_statement_lookup_1 (const char *const name, int constraint)
-{
-  struct out_section_hash_entry *entry;
-  struct out_section_hash_entry *last_ent;
-  unsigned long hash;
-
-  entry = ((struct out_section_hash_entry *)
-          bfd_hash_lookup (&output_section_statement_table, name,
-                           TRUE, FALSE));
-  if (entry == NULL)
-    {
-      einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+      if (create)
+       einfo (_("%P%F: failed creating section `%s': %E\n"), name);
       return NULL;
     }
 
@@ -1300,10 +1275,12 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
     {
       /* We have a section of this name, but it might not have the correct
         constraint.  */
-      hash = entry->root.hash;
+      struct out_section_hash_entry *last_ent;
+      unsigned long hash = entry->root.hash;
+
       do
        {
-         if (entry->s.output_section_statement.constraint != -1
+         if (entry->s.output_section_statement.constraint >= 0
              && (constraint == 0
                  || (constraint == entry->s.output_section_statement.constraint
                      && constraint != SPECIAL)))
@@ -1315,6 +1292,9 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
             && entry->root.hash == hash
             && strcmp (name, entry->s.output_section_statement.name) == 0);
 
+      if (!create)
+       return NULL;
+
       entry
        = ((struct out_section_hash_entry *)
           output_section_statement_newfunc (NULL,
@@ -1334,12 +1314,6 @@ lang_output_section_statement_lookup_1 (const char *const name, int constraint)
   return &entry->s.output_section_statement;
 }
 
-lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name)
-{
-  return lang_output_section_statement_lookup_1 (name, 0);
-}
-
 /* A variant of lang_output_section_find used by place_orphan.
    Returns the output statement that should precede a new output
    statement for SEC.  If an exact match is found on certain flags,
@@ -1502,7 +1476,7 @@ output_prev_sec_find (lang_output_section_statement_type *os)
 
   for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
     {
-      if (lookup->constraint == -1)
+      if (lookup->constraint < 0)
        continue;
 
       if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
@@ -3378,7 +3352,7 @@ map_input_to_output_sections
            {
              lang_output_section_statement_type *aos
                = (lang_output_section_statement_lookup
-                  (s->address_statement.section_name));
+                  (s->address_statement.section_name, 0, TRUE));
 
              if (aos->bfd_section == NULL)
                init_os (aos, NULL, 0);
@@ -3403,6 +3377,7 @@ process_insert_statements (void)
   lang_statement_union_type **s;
   lang_output_section_statement_type *first_os = NULL;
   lang_output_section_statement_type *last_os = NULL;
+  lang_output_section_statement_type *os;
 
   /* "start of list" is actually the statement immediately after
      the special abs_section output statement, so that it isn't
@@ -3415,6 +3390,12 @@ process_insert_statements (void)
          /* Keep pointers to the first and last output section
             statement in the sequence we may be about to move.  */
          last_os = &(*s)->output_section_statement;
+
+         /* Set constraint negative so that lang_output_section_find
+            won't match this output section statement.  At this
+            stage in linking constraint has values in the range
+            [-1, ONLY_IN_RW].  */
+         last_os->constraint = -2 - last_os->constraint;
          if (first_os == NULL)
            first_os = last_os;
        }
@@ -3422,7 +3403,6 @@ process_insert_statements (void)
        {
          lang_insert_statement_type *i = &(*s)->insert_statement;
          lang_output_section_statement_type *where;
-         lang_output_section_statement_type *os;
          lang_statement_union_type **ptr;
          lang_statement_union_type *first;
 
@@ -3431,21 +3411,12 @@ process_insert_statements (void)
            {
              do
                where = where->prev;
-             while (where != NULL && where->constraint == -1);
+             while (where != NULL && where->constraint < 0);
            }
          if (where == NULL)
            {
-             einfo (_("%X%P: %s not found for insert\n"), i->where);
-             continue;
-           }
-         /* You can't insert into the list you are moving.  */
-         for (os = first_os; os != NULL; os = os->next)
-           if (os == where || os == last_os)
-             break;
-         if (os == where)
-           {
-             einfo (_("%X%P: %s not found for insert\n"), i->where);
-             continue;
+             einfo (_("%F%P: %s not found for insert\n"), i->where);
+             return;
            }
 
          /* Deal with reordering the output section statement list.  */
@@ -3482,6 +3453,7 @@ process_insert_statements (void)
              last_sec = NULL;
              for (os = first_os; os != NULL; os = os->next)
                {
+                 os->constraint = -2 - os->constraint;
                  if (os->bfd_section != NULL
                      && os->bfd_section->owner != NULL)
                    {
@@ -3542,6 +3514,14 @@ process_insert_statements (void)
          s = &lang_output_section_statement.head;
        }
     }
+
+  /* Undo constraint twiddling.  */
+  for (os = first_os; os != NULL; os = os->next)
+    {
+      os->constraint = -2 - os->constraint;
+      if (os == last_os)
+       break;
+    }
 }
 
 /* An output section might have been removed after its statement was
@@ -3569,7 +3549,7 @@ strip_excluded_output_sections (void)
       asection *output_section;
       bfd_boolean exclude;
 
-      if (os->constraint == -1)
+      if (os->constraint < 0)
        continue;
 
       output_section = os->bfd_section;
@@ -5665,11 +5645,9 @@ lang_place_orphans (void)
                      || command_line.force_common_definition)
                    {
                      if (default_common_section == NULL)
-                       {
-                         default_common_section =
-                           lang_output_section_statement_lookup (".bss");
-
-                       }
+                       default_common_section
+                         = lang_output_section_statement_lookup (".bss", 0,
+                                                                 TRUE);
                      lang_add_section (&default_common_section->children, s,
                                        default_common_section);
                    }
@@ -5680,7 +5658,7 @@ lang_place_orphans (void)
                {
                  lang_output_section_statement_type *os;
 
-                 os = lang_output_section_statement_lookup (s->name);
+                 os = lang_output_section_statement_lookup (s->name, 0, TRUE);
                  lang_add_section (&os->children, s, os);
                }
            }
@@ -5827,12 +5805,10 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
 {
   lang_output_section_statement_type *os;
 
-  os = lang_output_section_statement_lookup_1 (output_section_statement_name,
-                                              constraint);
+  os = lang_output_section_statement_lookup (output_section_statement_name,
+                                            constraint, TRUE);
   current_section = os;
 
-  /* Make next things chain into subchain of this.  */
-
   if (os->addr_tree == NULL)
     {
       os->addr_tree = address_exp;
@@ -5843,6 +5819,8 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
   else
     os->flags = SEC_NEVER_LOAD;
   os->block_value = 1;
+
+  /* Make next things chain into subchain of this.  */
   stat_ptr = &os->children;
 
   os->subsection_alignment =
@@ -6639,7 +6617,7 @@ lang_record_phdrs (void)
        {
          lang_output_section_phdr_list *pl;
 
-         if (os->constraint == -1)
+         if (os->constraint < 0)
            continue;
 
          pl = os->phdrs;
@@ -6720,7 +6698,7 @@ lang_record_phdrs (void)
     {
       lang_output_section_phdr_list *pl;
 
-      if (os->constraint == -1
+      if (os->constraint < 0
          || os->bfd_section == NULL)
        continue;
 
index 4846197..8b652a8 100644 (file)
@@ -525,12 +525,13 @@ extern void lang_do_assignments
        statement != (lang_input_statement_type *) NULL;                        \
        statement = (lang_input_statement_type *) statement->next)      \
 
+#define lang_output_section_find(NAME) \
+  lang_output_section_statement_lookup (NAME, 0, FALSE)
+
 extern void lang_process
   (void);
 extern void ldlang_add_file
   (lang_input_statement_type *);
-extern lang_output_section_statement_type *lang_output_section_find
-  (const char * const);
 extern lang_output_section_statement_type *lang_output_section_find_by_flags
   (const asection *, lang_output_section_statement_type **,
    lang_match_sec_type_func);
@@ -541,9 +542,8 @@ extern lang_input_statement_type *lang_add_input_file
   (const char *, lang_input_file_enum_type, const char *);
 extern void lang_add_keepsyms_file
   (const char *);
-extern lang_output_section_statement_type *
-  lang_output_section_statement_lookup
-  (const char *const);
+extern lang_output_section_statement_type *lang_output_section_statement_lookup
+  (const char *const, int, bfd_boolean);
 extern void ldlang_add_undef
   (const char *const);
 extern void lang_add_output_format