GLD is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GLD is distributed in the hope that it will be useful,
 static void exp_init_os PARAMS ((etree_type *));
 static void section_already_linked PARAMS ((bfd *, asection *, PTR));
 static boolean wildcardp PARAMS ((const char *));
+static lang_statement_union_type *wild_sort
+  PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
+          asection *));
 static void wild_section PARAMS ((lang_wild_statement_type *ptr,
                                  const char *section,
                                  lang_input_statement_type *file,
 {
   lang_memory_region_type *m;
 
-  minfo ("\nMemory Configuration\n\n");
+  minfo (_("\nMemory Configuration\n\n"));
   fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
-          "Name", "Origin", "Length", "Attributes");
+          _("Name"), _("Origin"), _("Length"), _("Attributes"));
 
   for (m = lang_memory_region_list;
        m != (lang_memory_region_type *) NULL;
       print_nl ();
     }
 
-  fprintf (config.map_file, "\nLinker script and memory map\n\n");
+  fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
 
   print_statements ();
 }
     return;
 
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
-    einfo ("%P%F: Illegal use of `%s' section", DISCARD_SECTION_NAME);
+    einfo (_("%P%F: Illegal use of `%s' section"), DISCARD_SECTION_NAME);
 
   new = ((section_userdata_type *)
         stat_alloc (sizeof (section_userdata_type)));
     s->bfd_section = bfd_make_section (output_bfd, s->name);
   if (s->bfd_section == (asection *) NULL)
     {
-      einfo ("%P%F: output format %s cannot represent section called %s\n",
+      einfo (_("%P%F: output format %s cannot represent section called %s\n"),
             output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
              break;
 
            case SEC_LINK_DUPLICATES_ONE_ONLY:
-             einfo ("%P: %B: warning: ignoring duplicate section `%s'\n",
+             einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
                     abfd, name);
              break;
 
            case SEC_LINK_DUPLICATES_SAME_SIZE:
              if (bfd_section_size (abfd, sec)
                  != bfd_section_size (l->sec->owner, l->sec))
-               einfo ("%P: %B: warning: duplicate section `%s' has different size\n",
+               einfo (_("%P: %B: warning: duplicate section `%s' has different size\n"),
                       abfd, name);
              break;
            }
     }
 }
 
+/* Handle wildcard sorting.  This returns the lang_input_section which
+   should follow the one we are going to create for SECTION and FILE,
+   based on the sorting requirements of WILD.  It returns NULL if the
+   new section should just go at the end of the current list.  */
+
+static lang_statement_union_type *
+wild_sort (wild, file, section)
+     lang_wild_statement_type *wild;
+     lang_input_statement_type *file;
+     asection *section;
+{
+  const char *section_name;
+  lang_statement_union_type *l;
+
+  if (! wild->filenames_sorted && ! wild->sections_sorted)
+    return NULL;
+
+  section_name = bfd_get_section_name (file->the_bfd, section);
+  for (l = wild->children.head; l != NULL; l = l->next)
+    {
+      lang_input_section_type *ls;
+
+      if (l->header.type != lang_input_section_enum)
+       continue;
+      ls = &l->input_section;
+
+      /* Sorting by filename takes precedence over sorting by section
+         name.  */
+
+      if (wild->filenames_sorted)
+       {
+         int i;
+
+         i = strcmp (file->filename, ls->ifile->filename);
+         if (i < 0)
+           continue;
+         else if (i > 0)
+           break;
+       }
+
+      /* Here either the files are not sorted by name, or we are
+         looking at the sections for this file.  */
+
+      if (wild->sections_sorted)
+       {
+         if (strcmp (section_name,
+                     bfd_get_section_name (ls->ifile->the_bfd,
+                                           ls->section))
+             > 0)
+           break;
+       }
+    }
+
+  return l;
+}
+
 /* Expand a wild statement for a particular FILE.  SECTION may be
    NULL, in which case it is a wild card.  */
 
              else
                match = strcmp (section, name) == 0 ? true : false;
            }
+
          if (match)
-           wild_doit (&ptr->children, s, output, file);
+           {
+             lang_statement_union_type *before;
+
+             before = wild_sort (ptr, file, s);
+
+             /* Here BEFORE points to the lang_input_section which
+                should follow the one we are about to add.  If BEFORE
+                is NULL, then the section should just go at the end
+                of the current list.  */
+
+             if (before == NULL)
+               wild_doit (&ptr->children, s, output, file);
+             else
+               {
+                 lang_statement_list_type list;
+                 lang_statement_union_type **pp;
+
+                 lang_list_init (&list);
+                 wild_doit (&list, s, output, file);
+                 ASSERT (list.head != NULL && list.head->next == NULL);
+
+                 for (pp = &ptr->children.head;
+                      *pp != before;
+                      pp = &(*pp)->next)
+                   ASSERT (*pp != NULL);
+
+                 list.head->next = *pp;
+                 *pp = list.head;
+               }
+           }
        }
     }
 }
        {
          char **p;
 
-         einfo ("%B: file not recognized: %E\n", entry->the_bfd);
-         einfo ("%B: matching formats:", entry->the_bfd);
+         einfo (_("%B: file not recognized: %E\n"), entry->the_bfd);
+         einfo (_("%B: matching formats:"), entry->the_bfd);
          for (p = matching; *p != NULL; p++)
            einfo (" %s", *p);
          einfo ("%F\n");
        }
       else if (err != bfd_error_file_not_recognized
               || place == NULL)
-       einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
+       einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
 
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
          while (member != NULL)
            {
              if (! bfd_check_format (member, bfd_object))
-               einfo ("%F%B: object %B in archive is not object\n",
+               einfo (_("%F%B: object %B in archive is not object\n"),
                       entry->the_bfd, member);
              if (! ((*link_info.callbacks->add_archive_element)
                     (&link_info, member, "--whole-archive")))
                abort ();
              if (! bfd_link_add_symbols (member, &link_info))
-               einfo ("%F%B: could not read symbols: %E\n", member);
+               einfo (_("%F%B: could not read symbols: %E\n"), member);
              member = bfd_openr_next_archived_file (entry->the_bfd,
                                                     member);
            }
     }
 
   if (! bfd_link_add_symbols (entry->the_bfd, &link_info))
-    einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd);
+    einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);
 
   entry->loaded = true;
 }
     {
       if (bfd_get_error () == bfd_error_invalid_target)
        {
-         einfo ("%P%F: target %s not found\n", output_target);
+         einfo (_("%P%F: target %s not found\n"), output_target);
        }
-      einfo ("%P%F: cannot open output file %s: %E\n", name);
+      einfo (_("%P%F: cannot open output file %s: %E\n"), name);
     }
 
   delete_output_file_on_failure = true;
   /*  output->flags |= D_PAGED;*/
 
   if (! bfd_set_format (output, bfd_object))
-    einfo ("%P%F:%s: can not make object file: %E\n", name);
+    einfo (_("%P%F:%s: can not make object file: %E\n"), name);
   if (! bfd_set_arch_mach (output,
                           ldfile_output_architecture,
                           ldfile_output_machine))
-    einfo ("%P%F:%s: can not set architecture: %E\n", name);
+    einfo (_("%P%F:%s: can not set architecture: %E\n"), name);
 
   link_info.hash = bfd_link_hash_table_create (output);
   if (link_info.hash == (struct bfd_link_hash_table *) NULL)
-    einfo ("%P%F: can not create link hash table: %E\n");
+    einfo (_("%P%F: can not create link hash table: %E\n"));
 
   bfd_set_gp_size (output, g_switch_value);
   return output;
 
       h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
       if (h == (struct bfd_link_hash_entry *) NULL)
-       einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+       einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
       if (h->type == bfd_link_hash_new)
        {
          h->type = bfd_link_hash_undefined;
 
              addr = exp_get_abs_int (output_section_statement->load_base, 0,
                                      "load base", lang_final_phase_enum);
-             minfo (" load address 0x%V", addr);
+             minfo (_(" load address 0x%V"), addr);
            }
        }
 
                  --len;
                }
 
-             minfo ("%W (size before relaxing)\n", i->_raw_size);
+             minfo (_("%W (size before relaxing)\n"), i->_raw_size);
            }
 
          bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i);
 print_address_statement (address)
      lang_address_statement_type *address;
 {
-  minfo ("Address of section %s set to ", address->section_name);
+  minfo (_("Address of section %s set to "), address->section_name);
   exp_print_tree (address->address);
   print_nl ();
 }
 {
   print_space ();
 
+  if (w->filenames_sorted)
+    minfo ("SORT(");
   if (w->filename != NULL)
     minfo ("%s", w->filename);
   else
     minfo ("*");
+  if (w->filenames_sorted)
+    minfo (")");
 
+  minfo ("(");
+  if (w->sections_sorted)
+    minfo ("SORT(");
   if (w->section_name != NULL)
-    minfo ("(%s)", w->section_name);
+    minfo ("%s", w->section_name);
   else
-    minfo ("(*)");
+    minfo ("*");
+  if (w->sections_sorted)
+    minfo (")");
+  minfo (")");
 
   print_nl ();
 
   switch (s->header.type)
     {
     default:
-      fprintf (config.map_file, "Fail with %d\n", s->header.type);
+      fprintf (config.map_file, _("Fail with %d\n"), s->header.type);
       FAIL ();
       break;
     case lang_constructors_statement_enum:
           if (os->children.head == NULL
               || os->children.head->next != NULL
               || os->children.head->header.type != lang_input_section_enum)
-            einfo ("%P%X: Internal error on COFF shared library section %s\n",
+            einfo (_("%P%X: Internal error on COFF shared library section %s\n"),
                    os->name);
 
           input = os->children.head->input_section.section;
               && lang_memory_region_list != NULL
               && (strcmp (lang_memory_region_list->name, "*default*") != 0
                   || lang_memory_region_list->next != NULL))
-            einfo ("%P: warning: no memory region specified for section `%s'\n",
+            einfo (_("%P: warning: no memory region specified for section `%s'\n"),
                    bfd_get_section_name (output_bfd, os->bfd_section));
 
           dot = os->region->current;
               olddot = dot;
               dot = align_power (dot, os->bfd_section->alignment_power);
               if (dot != olddot && config.warn_section_align)
-                einfo ("%P: warning: changing start of section %s by %u bytes\n",
+                einfo (_("%P: warning: changing start of section %s by %u bytes\n"),
                        os->name, (unsigned int) (dot - olddot));
             }
         }
                              dot, &dot);
           if (r.valid == false)
           {
-            einfo ("%F%S: non constant address expression for section %s\n",
+            einfo (_("%F%S: non constant address expression for section %s\n"),
                    os->name);
           }
           dot = r.value + r.section->bfd_section->vma;
             {
               if (os->addr_tree != (etree_type *) NULL)
                 {
-                  einfo ("%X%P: address 0x%v of %B section %s is not within region %s\n",
+                  einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
                          os->region->current,
                          os->bfd_section->owner,
                          os->bfd_section->name,
                 }
               else
                 {
-                  einfo ("%X%P: region %s is full (%B section %s)\n",
+                  einfo (_("%X%P: region %s is full (%B section %s)\n"),
                          os->region->name,
                          os->bfd_section->owner,
                          os->bfd_section->name);
            boolean again;
 
            if (! bfd_relax_section (i->owner, i, &link_info, &again))
-             einfo ("%P%F: can't relax section: %E\n");
+             einfo (_("%P%F: can't relax section: %E\n"));
            if (again)
              relax_again = true;
          }
                      dot,
                      &newdot);
 
-       if (newdot != dot && !relax)
+       if (newdot != dot)
         {
           /* The assignment changed dot.  Insert a pad.  */
           if (output_section_statement == abs_output_section)
                  the default memory address.  */
               lang_memory_region_lookup ("*default*")->current = newdot;
             }
-          else
+          else if (!relax)
             {
               lang_statement_union_type *new =
                 ((lang_statement_union_type *)
                                   lang_final_phase_enum, dot, &dot);
            s->data_statement.value = value.value;
            if (value.valid == false)
-             einfo ("%F%P: invalid data statement\n");
+             einfo (_("%F%P: invalid data statement\n"));
          }
          switch (s->data_statement.type)
            {
                                   lang_final_phase_enum, dot, &dot);
            s->reloc_statement.addend_value = value.value;
            if (value.valid == false)
-             einfo ("%F%P: invalid reloc statement\n");
+             einfo (_("%F%P: invalid reloc statement\n"));
          }
          dot += bfd_get_reloc_size (s->reloc_statement.howto);
          break;
                                    h->u.def.section->output_section)
             + h->u.def.section->output_offset);
       if (! bfd_set_start_address (output_bfd, val))
-       einfo ("%P%F:%s: can't set start address\n", entry_symbol);
+       einfo (_("%P%F:%s: can't set start address\n"), entry_symbol);
     }
   else
     {
       if (ts != (asection *) NULL)
        {
          if (warn)
-           einfo ("%P: warning: cannot find entry symbol %s; defaulting to %V\n",
+           einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
                   entry_symbol, bfd_get_section_vma (output_bfd, ts));
          if (! bfd_set_start_address (output_bfd,
                                       bfd_get_section_vma (output_bfd, ts)))
-           einfo ("%P%F: can't set start address\n");
+           einfo (_("%P%F: can't set start address\n"));
        }
       else
        {
          if (warn)
-           einfo ("%P: warning: cannot find entry symbol %s; not setting start address\n",
+           einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
                   entry_symbol);
        }
     }
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
-           einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
+           einfo (_("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n"),
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (output_bfd));
        }
          if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
            {
              if (command_line.warn_mismatch)
-               einfo ("%E%X: failed to merge target specific data of file %B\n",
+               einfo (_("%E%X: failed to merge target specific data of file %B\n"),
                       input_bfd);
            }
          if (! command_line.warn_mismatch)
 
       if (! header_printed)
        {
-         minfo ("\nAllocating common symbols\n");
-         minfo ("Common symbol       size              file\n\n");
+         minfo (_("\nAllocating common symbols\n"));
+         minfo (_("Common symbol       size              file\n\n"));
          header_printed = true;
        }
 
                          /* This message happens when using the
                              svr3.ifile linker script, so I have
                              disabled it.  */
-                         info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
+                         info_msg (_("%P: no [COMMON] command, defaulting to .bss\n"));
 #endif
                          default_common_section =
                            lang_output_section_statement_lookup (".bss");
          break;
 
        default:
-         einfo ("%P%F: invalid syntax in flags\n");
+         einfo (_("%P%F: invalid syntax in flags\n"));
          break;
        }
       flags++;
 /* EXPORTED TO YACC */
 
 void
-lang_add_wild (section_name, filename)
-     CONST char *CONST section_name;
-     CONST char *CONST filename;
+lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
+     const char *const section_name;
+     boolean sections_sorted;
+     const char *const filename;
+     boolean filenames_sorted;
 {
   lang_wild_statement_type *new = new_stat (lang_wild_statement,
                                            stat_ptr);
       lang_has_input_file = true;
     }
   new->section_name = section_name;
+  new->sections_sorted = sections_sorted;
   new->filename = filename;
+  new->filenames_sorted = filenames_sorted;
   lang_list_init (&new->children);
 }
 
 {
   if (startup_file != (char *) NULL)
     {
-      einfo ("%P%Fmultiple STARTUP files\n");
+      einfo (_("%P%Fmultiple STARTUP files\n"));
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
 
   h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
   if (h == (struct bfd_link_hash_entry *) NULL)
-    einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
 
   if (h->type == bfd_link_hash_new
       || h->type == bfd_link_hash_undefined)
 
   h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
   if (h == (struct bfd_link_hash_entry *) NULL)
-    einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
 
   if (h->type == bfd_link_hash_new
       || h->type == bfd_link_hash_undefined)
                             flags,
                             l->at == NULL ? false : true,
                             at, l->filehdr, l->phdrs, c, secs))
-       einfo ("%F%P: bfd_record_phdr failed: %E\n");
+       einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
     }
 
   free (secs);
           pl != NULL;
           pl = pl->next)
        if (! pl->used && strcmp (pl->name, "NONE") != 0)
-         einfo ("%X%P: section `%s' assigned to non-existent phdr `%s'\n",
+         einfo (_("%X%P: section `%s' assigned to non-existent phdr `%s'\n"),
                 u->output_section_statement.name, pl->name);
     }
 }
   /* Make sure this node has a unique name.  */
   for (t = lang_elf_version_info; t != NULL; t = t->next)
     if (strcmp (t->name, name) == 0)
-      einfo ("%X%P: duplicate version tag `%s'\n", name);
+      einfo (_("%X%P: duplicate version tag `%s'\n"), name);
 
   /* Check the global and local match names, and make sure there
      aren't any duplicates.  */
 
          for (e2 = t->locals; e2 != NULL; e2 = e2->next)
            if (strcmp (e1->match, e2->match) == 0)
-             einfo ("%X%P: duplicate expression `%s' in version information\n",
+             einfo (_("%X%P: duplicate expression `%s' in version information\n"),
                     e1->match);
        }
     }
 
          for (e2 = t->globals; e2 != NULL; e2 = e2->next)
            if (strcmp (e1->match, e2->match) == 0)
-             einfo ("%X%P: duplicate expression `%s' in version information\n",
+             einfo (_("%X%P: duplicate expression `%s' in version information\n"),
                     e1->match);
        }
     }
        }
     }
 
-  einfo ("%X%P: unable to find version dependency `%s'\n", name);
+  einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
 
   return ret;
 }
 
 # Unusual variables checked by this code:
 #      NOP - two byte opcode for no-op (defaults to 0)
 #      DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
+#      INITIAL_READONLY_SECTIONS - at start of text segment
 #      OTHER_READONLY_SECTIONS - other than .text .init .rodata ...
 #              (e.g., .PARISC.milli)
+#      OTHER_TEXT_SECTIONS - these get put in .text when relocating
 #      OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
 #              (e.g., .PARISC.global)
 #      OTHER_SECTIONS - at the end
 #              .text section.
 #      DATA_START_SYMBOLS - symbols that appear at the start of the
 #              .data section.
+#      OTHER_GOT_SYMBOLS - symbols defined just before .got.
+#      OTHER_GOT_SECTIONS - sections just after .got and .sdata.
 #      OTHER_BSS_SYMBOLS - symbols that appear at the start of the
 #              .bss section besides __bss_start.
 #      DATA_PLT - .plt should be in data segment, not text segment.
+#      TEXT_DYNAMIC - .dynamic in text segment, not data segment.
 #      EMBEDDED - whether this is for an embedded system. 
+#      SHLIB_TEXT_START_ADDR - if set, add to SIZEOF_HEADERS to set
+#              start address of shared library.
 #
 # When adding sections, do note that the names of some sections are used
 # when specifying the start address of the next.
 #
+
 test -z "$ENTRY" && ENTRY=_start
 test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
 test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
 if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
+test -z "${ELFSIZE}" && ELFSIZE=32
 test "$LD_FLAG" = "N" && DATA_ADDR=.
 INTERP=".interp   ${RELOCATING-0} : { *(.interp)       }"
 PLT=".plt    ${RELOCATING-0} : { *(.plt)       }"
+DYNAMIC=".dynamic     ${RELOCATING-0} : { *(.dynamic) }"
 
 # if this is for an embedded system, don't add SIZEOF_HEADERS.
 if [ -z "$EMBEDDED" ]; then
 {
   /* Read-only sections, merged into text segment: */
   ${CREATE_SHLIB-${RELOCATING+. = ${TEXT_BASE_ADDRESS};}}
-  ${CREATE_SHLIB+${RELOCATING+. = SIZEOF_HEADERS;}}
+  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + SIZEOF_HEADERS;}}
   ${CREATE_SHLIB-${INTERP}}
+  ${INITIAL_READONLY_SECTIONS}
+  ${TEXT_DYNAMIC+${DYNAMIC}}
   .hash        ${RELOCATING-0} : { *(.hash)            }
   .dynsym      ${RELOCATING-0} : { *(.dynsym)          }
   .dynstr      ${RELOCATING-0} : { *(.dynstr)          }
   .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
   .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
   .rel.text    ${RELOCATING-0} :
-    { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+    { *(.rel.text) ${RELOCATING+*(.rel.gnu.linkonce.t*)} }
   .rela.text   ${RELOCATING-0} :
-    { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+    { *(.rela.text) ${RELOCATING+*(.rela.gnu.linkonce.t*)} }
   .rel.data    ${RELOCATING-0} :
-    { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+    { *(.rel.data) ${RELOCATING+*(.rel.gnu.linkonce.d*)} }
   .rela.data   ${RELOCATING-0} :
-    { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+    { *(.rela.data) ${RELOCATING+*(.rela.gnu.linkonce.d*)} }
   .rel.rodata  ${RELOCATING-0} :
-    { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+    { *(.rel.rodata) ${RELOCATING+*(.rel.gnu.linkonce.r*)} }
   .rela.rodata ${RELOCATING-0} :
-    { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+    { *(.rela.rodata) ${RELOCATING+*(.rela.gnu.linkonce.r*)} }
   .rel.got     ${RELOCATING-0} : { *(.rel.got)         }
   .rela.got    ${RELOCATING-0} : { *(.rela.got)                }
   .rel.ctors   ${RELOCATING-0} : { *(.rel.ctors)       }
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
     *(.text)
+    *(.stub)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
-    *(.gnu.linkonce.t*)
+    ${RELOCATING+*(.gnu.linkonce.t*)}
+    ${RELOCATING+${OTHER_TEXT_SECTIONS}}
   } =${NOP-0}
   ${RELOCATING+_etext = .;}
   ${RELOCATING+PROVIDE (etext = .);}
   .fini    ${RELOCATING-0} : { *(.fini)    } =${NOP-0}
-  .rodata  ${RELOCATING-0} : { *(.rodata) *(.gnu.linkonce.r*) }
+  .rodata  ${RELOCATING-0} : { *(.rodata) ${RELOCATING+*(.gnu.linkonce.r*)} }
   .rodata1 ${RELOCATING-0} : { *(.rodata1) }
   ${RELOCATING+${OTHER_READONLY_SECTIONS}}
 
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
-  ${RELOCATING+. = ${DATA_ADDR-ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))};}
+  ${CREATE_SHLIB-${RELOCATING+. = ${DATA_ADDR-ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))};}}
+  ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))};}}
 
   .data  ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
     *(.data)
-    *(.gnu.linkonce.d*)
+    ${RELOCATING+*(.gnu.linkonce.d*)}
     ${CONSTRUCTING+CONSTRUCTORS}
   }
   .data1 ${RELOCATING-0} : { *(.data1) }
   .ctors       ${RELOCATING-0} :
   {
     ${CONSTRUCTING+${CTOR_START}}
+    *(SORT(.ctors.*))
     *(.ctors)
     ${CONSTRUCTING+${CTOR_END}}
   }
   .dtors       ${RELOCATING-0} :
   {
     ${CONSTRUCTING+${DTOR_START}}
+    *(SORT(.dtors.*))
     *(.dtors)
     ${CONSTRUCTING+${DTOR_END}}
   }
   ${DATA_PLT+${PLT}}
+  ${RELOCATING+${OTHER_GOT_SYMBOLS}}
   .got         ${RELOCATING-0} : { *(.got.plt) *(.got) }
-  .dynamic     ${RELOCATING-0} : { *(.dynamic) }
+  ${TEXT_DYNAMIC-${DYNAMIC}}
   /* We want the small data sections together, so single-instruction offsets
      can access them all, and initialized data all before uninitialized, so
      we can shorten the on-disk segment size.  */
   .sdata   ${RELOCATING-0} : { *(.sdata) }
+  ${RELOCATING+${OTHER_GOT_SECTIONS}}
   ${RELOCATING+_edata  =  .;}
   ${RELOCATING+PROVIDE (edata = .);}
   ${RELOCATING+__bss_start = .;}
    *(.bss)
    *(COMMON)
   }
+  ${RELOCATING+. = ALIGN(${ELFSIZE} / 8);}
   ${RELOCATING+_end = . ;}
   ${RELOCATING+PROVIDE (end = .);}
 
 
--- /dev/null
+#
+# Unusual variables checked by this code:
+#      NOP - two byte opcode for no-op (defaults to 0)
+#      DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
+#      OTHER_READONLY_SECTIONS - other than .text .init .rodata ...
+#              (e.g., .PARISC.milli)
+#      OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
+#              (e.g., .PARISC.global)
+#      OTHER_SECTIONS - at the end
+#      EXECUTABLE_SYMBOLS - symbols that must be defined for an
+#              executable (e.g., _DYNAMIC_LINK)
+#      TEXT_START_SYMBOLS - symbols that appear at the start of the
+#              .text section.
+#      DATA_START_SYMBOLS - symbols that appear at the start of the
+#              .data section.
+#      OTHER_BSS_SYMBOLS - symbols that appear at the start of the
+#              .bss section besides __bss_start.
+#      DATA_PLT - .plt should be in data segment, not text segment.
+#      EMBEDDED - whether this is for an embedded system. 
+#
+# When adding sections, do note that the names of some sections are used
+# when specifying the start address of the next.
+#
+test -z "$ENTRY" && ENTRY=_start
+test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
+test "$LD_FLAG" = "N" && DATA_ADDR=.
+INTERP=".interp   ${RELOCATING-0} : { *(.interp)       }"
+PLT=".plt    ${RELOCATING-0} : { *(.plt)       }"
+
+# if this is for an embedded system, don't add SIZEOF_HEADERS.
+if [ -z "$EMBEDDED" ]; then
+   test -z "${READONLY_BASE_ADDRESS}" && READONLY_BASE_ADDRESS="${READONLY_START_ADDR} + SIZEOF_HEADERS"
+else
+   test -z "${READONLY_BASE_ADDRESS}" && READONLY_BASE_ADDRESS="${READONLY_START_ADDR}"
+fi
+
+cat <<EOF
+OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
+             "${LITTLE_OUTPUT_FORMAT}")
+OUTPUT_ARCH(${OUTPUT_ARCH})
+ENTRY(${ENTRY})
+
+${RELOCATING+${LIB_SEARCH_DIRS}}
+${RELOCATING+/* Do we need any of these for elf?
+   __DYNAMIC = 0; ${STACKZERO+${STACKZERO}} ${SHLIB_PATH+${SHLIB_PATH}}  */}
+${RELOCATING+${EXECUTABLE_SYMBOLS}}
+${RELOCATING- /* For some reason, the Solaris linker makes bad executables
+  if gld -r is used and the intermediate file has sections starting
+  at non-zero addresses.  Could be a Solaris ld bug, could be a GNU ld
+  bug.  But for now assigning the zero vmas works.  */}
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  ${CREATE_SHLIB-${RELOCATING+. = ${READONLY_BASE_ADDRESS};}}
+  ${CREATE_SHLIB+${RELOCATING+. = SIZEOF_HEADERS;}}
+  ${CREATE_SHLIB-${INTERP}}
+  .hash        ${RELOCATING-0} : { *(.hash)            }
+  .dynsym      ${RELOCATING-0} : { *(.dynsym)          }
+  .dynstr      ${RELOCATING-0} : { *(.dynstr)          }
+  .rel.text    ${RELOCATING-0} : { *(.rel.text)                }
+  .rela.text   ${RELOCATING-0} : { *(.rela.text)       }
+  .rel.data    ${RELOCATING-0} : { *(.rel.data)                }
+  .rela.data   ${RELOCATING-0} : { *(.rela.data)       }
+  .rel.rodata  ${RELOCATING-0} : { *(.rel.rodata)      }
+  .rela.rodata ${RELOCATING-0} : { *(.rela.rodata)     }
+  .rel.got     ${RELOCATING-0} : { *(.rel.got)         }
+  .rela.got    ${RELOCATING-0} : { *(.rela.got)                }
+  .rel.ctors   ${RELOCATING-0} : { *(.rel.ctors)       }
+  .rela.ctors  ${RELOCATING-0} : { *(.rela.ctors)      }
+  .rel.dtors   ${RELOCATING-0} : { *(.rel.dtors)       }
+  .rela.dtors  ${RELOCATING-0} : { *(.rela.dtors)      }
+  .rel.init    ${RELOCATING-0} : { *(.rel.init)        }
+  .rela.init   ${RELOCATING-0} : { *(.rela.init)       }
+  .rel.fini    ${RELOCATING-0} : { *(.rel.fini)        }
+  .rela.fini   ${RELOCATING-0} : { *(.rela.fini)       }
+  .rel.bss     ${RELOCATING-0} : { *(.rel.bss)         }
+  .rela.bss    ${RELOCATING-0} : { *(.rela.bss)                }
+  .rel.plt     ${RELOCATING-0} : { *(.rel.plt)         }
+  .rela.plt    ${RELOCATING-0} : { *(.rela.plt)                }
+  ${DATA_PLT-${PLT}}
+  .rodata  ${RELOCATING-0} : { *(.rodata) *(.gnu.linkonce.r*) }
+  .rodata1 ${RELOCATING-0} : { *(.rodata1) }
+  ${RELOCATING+${OTHER_READONLY_SECTIONS}}
+
+  /* Adjust the address for the data segment.  */
+  ${RELOCATING+. = ${DATA_ADDR-ALIGN(4);}}
+
+  .data  ${RELOCATING-0} :
+  {
+    ${RELOCATING+${DATA_START_SYMBOLS}}
+    *(.data)
+    *(.gnu.linkonce.d*)
+    ${CONSTRUCTING+CONSTRUCTORS}
+  }
+  .data1 ${RELOCATING-0} : { *(.data1) }
+  ${RELOCATING+${OTHER_READWRITE_SECTIONS}}
+  .ctors       ${RELOCATING-0} :
+  {
+    ${CONSTRUCTING+${CTOR_START}}
+    *(SORT(.ctors.*))
+    *(.ctors)
+    ${CONSTRUCTING+${CTOR_END}}
+  }
+  .dtors       ${RELOCATING-0} :
+  {
+    ${CONSTRUCTING+${DTOR_START}}
+    *(SORT(.dtors.*))
+    *(.dtors)
+    ${CONSTRUCTING+${DTOR_END}}
+  }
+  .got         ${RELOCATING-0} : { *(.got.plt) *(.got) }
+  .dynamic     ${RELOCATING-0} : { *(.dynamic) }
+  ${DATA_PLT+${PLT}}
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata   ${RELOCATING-0} : { *(.sdata) }
+  ${RELOCATING+_edata  =  .;}
+  ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+__bss_start = .;}
+  ${RELOCATING+${OTHER_BSS_SYMBOLS}}
+  .sbss    ${RELOCATING-0} : { *(.sbss) *(.scommon) }
+  .bss     ${RELOCATING-0} :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  ${RELOCATING+_end = . ;}
+  ${RELOCATING+PROVIDE (end = .);}
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+
+  .comment 0 : { *(.comment) }
+
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+
+  ${RELOCATING+${OTHER_RELOCATING_SECTIONS}}
+
+  /* These must appear regardless of ${RELOCATING}.  */
+  ${OTHER_SECTIONS}
+
+
+  /* Hmmm, there's got to be a better way.  This sets the stack to the
+     top of the simulator memory (i.e. top of 64K data space). */
+  .stack 0x00007FFE : { _stack = .; *(.stack) }
+
+  .text    ${RELOCATING+${TEXT_START_ADDR}} :
+  {
+    ${RELOCATING+${TEXT_START_SYMBOLS}}
+    *(.init)
+    *(.fini)
+    *(.text)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.gnu.linkonce.t*)
+  } =${NOP-0}
+  ${RELOCATING+_etext = .;}
+  ${RELOCATING+PROVIDE (etext = .);}
+}
+EOF