2002-03-26 Fred Fish <fnf@redhat.com>
[deliverable/binutils-gdb.git] / bfd / xcofflink.c
index 199576989262ce59dd857c6944b0b48c369d9fd2..c122aeffb80f16c8ab6d71c7a1ccafc789b35ac8 100644 (file)
@@ -1,23 +1,23 @@
 /* POWER/PowerPC XCOFF linker support.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program 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 2 of the License, or
-(at your option) any later version.
+   This program 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 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -588,11 +588,11 @@ _bfd_xcoff_bfd_link_add_symbols (abfd, info)
 
     case bfd_archive:
       /* If the archive has a map, do the usual search.  We then need
-         to check the archive for stripped dynamic objects, because
-         they will not appear in the archive map even though they
-         should, perhaps, be included.  If the archive has no map, we
-         just consider each object file in turn, since that apparently
-         is what the AIX native linker does.  */
+         to check the archive for dynamic objects, because they may not 
+        appear in the archive map even though they should, perhaps, be 
+        included.  If the archive has no map, we just consider each object 
+        file in turn, since that apparently is what the AIX native linker 
+        does.  */
       if (bfd_has_map (abfd))
        {
          if (! (_bfd_generic_link_add_archive_symbols
@@ -602,18 +602,18 @@ _bfd_xcoff_bfd_link_add_symbols (abfd, info)
 
       {
        bfd *member;
-
+       
        member = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
        while (member != NULL)
          {
            if (bfd_check_format (member, bfd_object)
-               && (! bfd_has_map (abfd)
-                   || ((member->flags & DYNAMIC) != 0
-                       && (member->flags & HAS_SYMS) == 0)))
+               && (info->hash->creator == member->xvec)
+               && (! bfd_has_map (abfd) || (member->flags & DYNAMIC) != 0))
              {
                boolean needed;
-
-               if (! xcoff_link_check_archive_element (member, info, &needed))
+               
+               if (! xcoff_link_check_archive_element (member, info, 
+                                                       &needed))
                  return false;
                if (needed)
                  member->archive_pass = -1;
@@ -1046,16 +1046,12 @@ xcoff_link_add_symbols (abfd, info)
       && ! info->static_link)
     {
       if (! xcoff_link_add_dynamic_symbols (abfd, info))
-       {
-         return false;
-       }
+       return false;
     }
 
   /* create the loader, toc, gl, ds and debug sections, if needed */
   if (false == xcoff_link_create_extra_sections(abfd, info))
-    {
-      goto error_return;
-    }
+    goto error_return;
 
   if ((abfd->flags & DYNAMIC) != 0
       && ! info->static_link)
@@ -1146,7 +1142,6 @@ xcoff_link_add_symbols (abfd, info)
        }
     }
 
-
   /* Don't let the linker relocation routines discard the symbols.  */
   obj_coff_keep_syms (abfd) = true;
 
@@ -2806,7 +2801,7 @@ boolean
 bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
                                 file_align, maxstack, maxdata, gc,
                                 modtype, textro, export_defineds,
-                                special_sections)
+                                special_sections, rtld)
      bfd *output_bfd;
      struct bfd_link_info *info;
      const char *libpath;
@@ -2819,6 +2814,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
      boolean textro;
      boolean export_defineds;
      asection **special_sections;
+     boolean rtld;
 {
   struct xcoff_link_hash_entry *hentry;
   asection *lsec;
@@ -2837,7 +2833,6 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
 
   if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
     {
-
       for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
        special_sections[i] = NULL;
       return true;
@@ -2859,11 +2854,8 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   xcoff_hash_table (info)->file_align = file_align;
   xcoff_hash_table (info)->textro = textro;
 
-  if (entry == NULL)
-    {
-      hentry = NULL;
-    }
-  else
+  hentry = NULL;
+  if (entry != NULL)
     {
       hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
                                       false, false, true);
@@ -2872,65 +2864,56 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
     }
 
   /* __rtinit */
-  if (info->init_function || info->fini_function) {
-    struct xcoff_link_hash_entry *hrtinit;
-    struct internal_ldsym *ldsym;
-
-    hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info),
-                                     "__rtinit",
-                                     false, false, true);
-    if (hrtinit != NULL)
-      {
-       xcoff_mark_symbol (info, hrtinit);
-       hrtinit->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
-      }
-    else
-      {
-       (*_bfd_error_handler)
-         (_("error: undefined symbol __rtinit"));
-
-       return false;
-      }
-
-    /* __rtinit initalized here
-       Some information, like the location of the .initfini seciton will
-       be filled in later.
-
-       name or offset taken care of below with bfd_xcoff_put_ldsymbol_name.  */
-    amt = sizeof (struct internal_ldsym);
-    ldsym = (struct internal_ldsym *) bfd_malloc (amt);
-
-    ldsym->l_value = 0;                  /* will be filled in later */
-    ldsym->l_scnum = 2;                  /* data section */
-    ldsym->l_smtype = XTY_SD;            /* csect section definition */
-    ldsym->l_smclas = 5;                 /* .rw */
-    ldsym->l_ifile = 0;                  /* special system loader symbol */
-    ldsym->l_parm = 0;                   /* NA */
-
-    /* Force __rtinit to be the first symbol in the loader symbol table
-       See xcoff_build_ldsyms
-
-       The first 3 symbol table indices are reserved to indicate the data,
-       text and bss sections.  */
-    BFD_ASSERT (0 == ldinfo.ldsym_count);
-
-    hrtinit->ldindx = 3;
-    ldinfo.ldsym_count = 1;
-    hrtinit->ldsym = ldsym;
-
-    if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
-                                             hrtinit->ldsym,
-                                             hrtinit->root.root.string))
-      {
+  if (info->init_function || info->fini_function || rtld == true) 
+    {
+      struct xcoff_link_hash_entry *hsym;
+      struct internal_ldsym *ldsym;
+      
+      hsym = xcoff_link_hash_lookup (xcoff_hash_table (info),
+                                    "__rtinit", false, false, true);
+      if (hsym == NULL)
+       {
+         (*_bfd_error_handler)
+           (_("error: undefined symbol __rtinit"));
+         return false;
+       }
+      
+      xcoff_mark_symbol (info, hsym);
+      hsym->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
+
+      /* __rtinit initalized */
+      amt = sizeof (struct internal_ldsym);
+      ldsym = (struct internal_ldsym *) bfd_malloc (amt);
+      
+      ldsym->l_value = 0;                  /* will be filled in later */
+      ldsym->l_scnum = 2;                  /* data section */
+      ldsym->l_smtype = XTY_SD;            /* csect section definition */
+      ldsym->l_smclas = 5;                 /* .rw */
+      ldsym->l_ifile = 0;                  /* special system loader symbol */
+      ldsym->l_parm = 0;                   /* NA */
+      
+      /* Force __rtinit to be the first symbol in the loader symbol table
+        See xcoff_build_ldsyms
+        
+        The first 3 symbol table indices are reserved to indicate the data,
+        text and bss sections.  */
+      BFD_ASSERT (0 == ldinfo.ldsym_count);
+      
+      hsym->ldindx = 3;
+      ldinfo.ldsym_count = 1;
+      hsym->ldsym = ldsym;
+      
+      if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
+                                               hsym->ldsym,
+                                               hsym->root.root.string))
        return false;
-      }
-
-    /* This symbol is written out by xcoff_write_global_symbol
-       Set stuff up so xcoff_write_global_symbol logic works.  */
-    hrtinit->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
-    hrtinit->root.type = bfd_link_hash_defined;
-    hrtinit->root.u.def.value = 0;
-  }
+      
+      /* This symbol is written out by xcoff_write_global_symbol
+        Set stuff up so xcoff_write_global_symbol logic works.  */
+      hsym->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
+      hsym->root.type = bfd_link_hash_defined;
+      hsym->root.u.def.value = 0;
+    }
 
   /* Garbage collect unused sections.  */
   if (info->relocateable
@@ -3158,37 +3141,42 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
 
       csectpp = xcoff_data (sub)->csects;
 
-      symesz = bfd_coff_symesz (sub);
-      esym = (bfd_byte *) obj_coff_external_syms (sub);
-      esymend = esym + symcount * symesz;
-      while (esym < esymend)
+      /* Dynamic object do not have csectpp's.  */
+      if (NULL != csectpp) 
        {
-         struct internal_syment sym;
+         symesz = bfd_coff_symesz (sub);
+         esym = (bfd_byte *) obj_coff_external_syms (sub);
+         esymend = esym + symcount * symesz;
 
-         bfd_coff_swap_sym_in (sub, (PTR) esym, (PTR) &sym);
+         while (esym < esymend)
+           {
+             struct internal_syment sym;
 
-         *debug_index = (unsigned long) -1;
+             bfd_coff_swap_sym_in (sub, (PTR) esym, (PTR) &sym);
 
-         if (sym._n._n_n._n_zeroes == 0
-             && *csectpp != NULL
-             && (! gc
-                 || ((*csectpp)->flags & SEC_MARK) != 0
-                 || *csectpp == bfd_abs_section_ptr)
-             && bfd_coff_symname_in_debug (sub, &sym))
-           {
-             char *name;
-             bfd_size_type indx;
+             *debug_index = (unsigned long) -1;
 
-             name = (char *) debug_contents + sym._n._n_n._n_offset;
-             indx = _bfd_stringtab_add (debug_strtab, name, true, true);
-             if (indx == (bfd_size_type) -1)
-               goto error_return;
-             *debug_index = indx;
-           }
+             if (sym._n._n_n._n_zeroes == 0
+                 && *csectpp != NULL
+                 && (! gc
+                     || ((*csectpp)->flags & SEC_MARK) != 0
+                     || *csectpp == bfd_abs_section_ptr)
+                 && bfd_coff_symname_in_debug (sub, &sym))
+               {
+                 char *name;
+                 bfd_size_type indx;
 
-         esym += (sym.n_numaux + 1) * symesz;
-         csectpp += sym.n_numaux + 1;
-         debug_index += sym.n_numaux + 1;
+                 name = (char *) debug_contents + sym._n._n_n._n_offset;
+                 indx = _bfd_stringtab_add (debug_strtab, name, true, true);
+                 if (indx == (bfd_size_type) -1)
+                   goto error_return;
+                 *debug_index = indx;
+               }
+
+             esym += (sym.n_numaux + 1) * symesz;
+             csectpp += sym.n_numaux + 1;
+             debug_index += sym.n_numaux + 1;
+           }
        }
 
       free (debug_contents);
@@ -3220,10 +3208,11 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
 }
 
 boolean 
-bfd_xcoff_link_generate_rtinit (abfd, init, fini)
+bfd_xcoff_link_generate_rtinit (abfd, init, fini, rtld)
      bfd *abfd;
      const char *init;
      const char *fini;
+     boolean rtld;
 {
   struct bfd_in_memory *bim;
   
@@ -3242,7 +3231,7 @@ bfd_xcoff_link_generate_rtinit (abfd, init, fini)
   abfd->direction = write_direction;
   abfd->where = 0;
 
-  if (false == bfd_xcoff_generate_rtinit (abfd, init, fini)) 
+  if (false == bfd_xcoff_generate_rtinit (abfd, init, fini, rtld)) 
     return false;
 
   /* need to reset to unknown or it will not be read back in correctly */
@@ -3264,14 +3253,9 @@ xcoff_build_ldsyms (h, p)
   struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
   bfd_size_type amt;
 
-  /* __rtinit
-     Special handling of this symbol to make is the first symbol in
-     the loader symbol table.  Make sure this pass through does not
-     undo it.  */
+  /* __rtinit, this symbol has special handling. */
   if (h->flags & XCOFF_RTINIT)
-    {
       return true;
-    }
 
   /* If this is a final link, and the symbol was defined as a common
      symbol in a regular object file, and there was no definition in
@@ -3386,17 +3370,11 @@ xcoff_build_ldsyms (h, p)
             xcoff32 uses 4 bytes in the toc.
             xcoff64 uses 8 bytes in the toc.  */
          if (bfd_xcoff_is_xcoff64 (ldinfo->output_bfd))
-           {
-             byte_size = 8;
-           }
+           byte_size = 8;
          else if (bfd_xcoff_is_xcoff32 (ldinfo->output_bfd))
-           {
-             byte_size = 4;
-           }
+           byte_size = 4;
          else
-           {
-             return false;
-           }
+           return false;
 
          hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
          hds->u.toc_offset = hds->toc_section->_raw_size;
@@ -3656,15 +3634,14 @@ _bfd_xcoff_bfd_final_link (abfd, info)
        {
          boolean saw_contents;
          int indx;
-         asection **op, **prev;
+         asection **op;
          file_ptr sofar;
          
          /* Insert .pad sections before every section which has
              contents and is loaded, if it is preceded by some other
              section which has contents and is loaded.  */
          saw_contents = true;
-         for (op = &abfd->sections, prev = NULL; 
-              *op != NULL; prev = op, op = &(*op)->next)
+         for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
            {
              if (strcmp ((*op)->name, ".pad") == 0)
                saw_contents = false;
@@ -3675,34 +3652,22 @@ _bfd_xcoff_bfd_final_link (abfd, info)
                    saw_contents = true;
                  else
                    {
-                     asection *n, *hold, **st;
+                     asection *n, **st;
                      
                      /* Create a pad section and place it before the section
                         that needs padding.  This requires unlinking and 
-                        relinking the bfd's sections list. 
-                        
-                        sections = S1
-                        .          S1.next = S2
-                        .          S2.next = S3
-                        .          S3.next = NULL
-                        section_tail = &S3.next */
+                        relinking the bfd's section list.  */
                      
-                     hold = *op;
                      st = abfd->section_tail;
-                     
                      n = bfd_make_section_anyway (abfd, ".pad");
                      n->flags = SEC_HAS_CONTENTS;
                      n->alignment_power = 0; 
-                     
-                     if (NULL == prev) 
-                       abfd->sections = n;
-                     else
-                       (*prev)->next = n;
-                     
-                     n->next = hold;
-                     *st = NULL;
-                     abfd->section_tail = st;
 
+                     BFD_ASSERT (*st == n);
+                     bfd_section_list_remove (abfd, st);
+                     bfd_section_list_insert (abfd, op, n);
+
+                     op = &n->next;
                      saw_contents = false;
                    }
                }
This page took 0.030022 seconds and 4 git commands to generate.