Fix list handling for orphan section output statements.
authorAlan Modra <amodra@gmail.com>
Thu, 7 Sep 2000 07:08:58 +0000 (07:08 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 7 Sep 2000 07:08:58 +0000 (07:08 +0000)
ld/ChangeLog
ld/emultempl/elf32.em

index e9ca6841a424e5ef618c1b5610315beb1529bbc9..0292f837f21b1b7341f11187d13c0ca8e1bfedb6 100644 (file)
@@ -1,3 +1,10 @@
+2000-09-07  Alan Modra  <alan@linuxcare.com.au>
+
+       * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Fix
+       broken list handling.  Create __start_SECNAME and __stop_SECNAME
+       when no place-holder.  Add some comments.  Test both SEC_CODE and
+       SEC_READONLY for hold_text to prevent .rodata orphan poisoning.
+
 2000-09-07  Niibe Yutaka  <gniibe@m17n.org>, Kaz Kojima  <kkojima@rr.iij4u.or.jp>, Alexandre Oliva  <aoliva@redhat.com>
 
        * configure.tgt (sh-*-linux*): Added.
index 717f931114ceca81213e6a6001378fcad8d3f7a1..037ac5aec9bea343fb83c8561e7d98da934e1737 100644 (file)
@@ -1010,7 +1010,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
   static struct orphan_save hold_interp;
   static int count = 1;
   struct orphan_save *place;
-  lang_statement_list_type *old = NULL;
+  lang_statement_list_type *old;
   lang_statement_list_type add;
   etree_type *address;
   const char *secname;
@@ -1060,8 +1060,10 @@ gld${EMULATION_NAME}_place_orphan (file, s)
 
   if (s->flags & SEC_EXCLUDE)
     return false;
-  else if ((s->flags & SEC_ALLOC) == 0)
-    place = NULL;
+
+  place = NULL;
+  if ((s->flags & SEC_ALLOC) == 0)
+    ;
   else if ((s->flags & SEC_LOAD) != 0
           && strncmp (secname, ".note", 4) == 0
           && HAVE_SECTION (hold_interp, ".interp"))
@@ -1076,15 +1078,12 @@ gld${EMULATION_NAME}_place_orphan (file, s)
           && (hold_rel.os != NULL
               || (hold_rel.os = output_rel_find ()) != NULL))
     place = &hold_rel;
-  else if ((s->flags & SEC_CODE) == 0
-          && (s->flags & SEC_READONLY) != 0
+  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
           && HAVE_SECTION (hold_rodata, ".rodata"))
     place = &hold_rodata;
-  else if ((s->flags & SEC_READONLY) != 0
+  else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY)
           && hold_text.os != NULL)
     place = &hold_text;
-  else
-    place = NULL;
 
 #undef HAVE_SECTION
 
@@ -1097,19 +1096,27 @@ gld${EMULATION_NAME}_place_orphan (file, s)
                                              outsecname,
                                              &count);
 
+  /* Start building a list of statements for this section.
+     First save the current statement pointer.  */
+  old = stat_ptr;
+
+  /* If we have found an appropriate place for the output section
+     statements for this orphan, add them to our own private list,
+     inserting them later into the global statement list.  */
   if (place != NULL)
     {
-      /* Start building a list of statements for this section.  */
-      old = stat_ptr;
       stat_ptr = &add;
       lang_list_init (stat_ptr);
+    }
 
+  if (config.build_constructors)
+    {
       /* If the name of the section is representable in C, then create
         symbols to mark the start and the end of the section.  */
       for (ps = outsecname; *ps != '\0'; ps++)
        if (! isalnum ((unsigned char) *ps) && *ps != '_')
          break;
-      if (*ps == '\0' && config.build_constructors)
+      if (*ps == '\0')
        {
          char *symname;
          etree_type *e_align;
@@ -1139,29 +1146,35 @@ gld${EMULATION_NAME}_place_orphan (file, s)
     ((bfd_vma) 0, "*default*",
      (struct lang_output_section_phdr_list *) NULL, "*default*");
 
-  if (place != NULL)
+  if (config.build_constructors && *ps == '\0')
     {
-      asection *snew, **pps;
+      char *symname;
 
-      stat_ptr = &add;
+      /* lang_leave_ouput_section_statement resets stat_ptr.  Put
+        stat_ptr back where we want it.  */
+      if (place != NULL)
+       stat_ptr = &add;
 
-      if (*ps == '\0' && config.build_constructors)
-       {
-         char *symname;
+      symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
+      sprintf (symname, "__stop_%s", outsecname);
+      lang_add_assignment (exp_assop ('=', symname,
+                                     exp_nameop (NAME, ".")));
+    }
 
-         symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
-         sprintf (symname, "__stop_%s", outsecname);
-         lang_add_assignment (exp_assop ('=', symname,
-                                         exp_nameop (NAME, ".")));
-       }
-      stat_ptr = old;
+  /* Restore the global list pointer.  */
+  stat_ptr = old;
+
+  if (place != NULL)
+    {
+      asection *snew, **pps;
 
       snew = os->bfd_section;
       if (place->section != NULL
          || (place->os->bfd_section != NULL
              && place->os->bfd_section != snew))
        {
-         /* Shuffle the section to make the output file look neater.  */
+         /* Shuffle the section to make the output file look neater.
+            This is really only cosmetic.  */
          if (place->section == NULL)
            {
 #if 0
@@ -1190,6 +1203,9 @@ gld${EMULATION_NAME}_place_orphan (file, s)
        }
       place->section = &snew->next;    /* Save the end of this list.  */
 
+      /* We try to put the output statements in some sort of
+        reasonable order here, because they determine the final load
+        addresses of the orphan sections.  */
       if (place->stmt == NULL)
        {
          /* Put the new statement list right at the head.  */
@@ -1202,7 +1218,14 @@ gld${EMULATION_NAME}_place_orphan (file, s)
          *add.tail = *place->stmt;
          *place->stmt = add.head;
        }
-      place->stmt = add.tail;          /* Save the end of this list.  */
+
+      /* Fix the global list pointer if we happened to tack our new
+        list at the tail.  */
+      if (*old->tail == add.head)
+       old->tail = add.tail;
+
+      /* Save the end of this list.  */
+      place->stmt = add.tail;
     }
 
   return true;