include/coff/
[deliverable/binutils-gdb.git] / bfd / xcofflink.c
index 39d278ec6dd1596578e673fa32a1550c3344a2d1..da5944eb818ff89b0918d1f30206db5da2171adf 100644 (file)
@@ -258,7 +258,12 @@ _bfd_xcoff_canonicalize_dynamic_symtab (bfd *abfd, asymbol **psyms)
 
       symbuf->symbol.flags = BSF_NO_FLAGS;
       if ((ldsym.l_smtype & L_EXPORT) != 0)
-       symbuf->symbol.flags |= BSF_GLOBAL;
+       {
+         if ((ldsym.l_smtype & L_WEAK) != 0)
+           symbuf->symbol.flags |= BSF_WEAK;
+         else
+           symbuf->symbol.flags |= BSF_GLOBAL;
+       }
 
       /* FIXME: We have no way to record the other information stored
         with the loader symbol.  */
@@ -540,6 +545,36 @@ xcoff_read_internal_relocs (bfd *abfd,
                                         require_internal, internal_relocs);
 }
 \f
+/* H is the bfd symbol associated with exported .loader symbol LDSYM.
+   Return true if LDSYM defines H.  */
+
+static bfd_boolean
+xcoff_dynamic_definition_p (struct xcoff_link_hash_entry *h,
+                           struct internal_ldsym *ldsym)
+{
+  /* If we didn't know about H before processing LDSYM, LDSYM
+     definitely defines H.  */
+  if (h->root.type == bfd_link_hash_new)
+    return TRUE;
+
+  /* If H is currently a weak dynamic symbol, and if LDSYM is a strong
+     dynamic symbol, LDSYM trumps the current definition of H.  */
+  if ((ldsym->l_smtype & L_WEAK) == 0
+      && (h->flags & XCOFF_DEF_DYNAMIC) != 0
+      && (h->flags & XCOFF_DEF_REGULAR) == 0
+      && (h->root.type == bfd_link_hash_defweak
+         || h->root.type == bfd_link_hash_undefweak))
+    return TRUE;
+
+  /* If H is currently undefined, LDSYM defines it.  */
+  if ((h->flags & XCOFF_DEF_DYNAMIC) == 0
+      && (h->root.type == bfd_link_hash_undefined
+         || h->root.type == bfd_link_hash_undefweak))
+    return TRUE;
+
+  return FALSE;
+}
+
 /* This function is used to add symbols from a dynamic object to the
    global symbol table.  */
 
@@ -638,43 +673,33 @@ xcoff_link_add_dynamic_symbols (bfd *abfd, struct bfd_link_info *info)
       if (h == NULL)
        return FALSE;
 
-      h->flags |= XCOFF_DEF_DYNAMIC;
-
-      /* If the symbol is undefined, and the BFD it was found in is
-        not a dynamic object, change the BFD to this dynamic object,
-        so that we can get the correct import file ID.  */
-      if ((h->root.type == bfd_link_hash_undefined
-          || h->root.type == bfd_link_hash_undefweak)
-         && (h->root.u.undef.abfd == NULL
-             || (h->root.u.undef.abfd->flags & DYNAMIC) == 0))
-       h->root.u.undef.abfd = abfd;
-
-      if (h->root.type == bfd_link_hash_new)
-       {
-         h->root.type = bfd_link_hash_undefined;
-         h->root.u.undef.abfd = abfd;
-         /* We do not want to add this to the undefined symbol list.  */
-       }
-
-      if (h->smclas == XMC_UA
-         || h->root.type == bfd_link_hash_undefined
-         || h->root.type == bfd_link_hash_undefweak)
-       h->smclas = ldsym.l_smclas;
-
-      /* Unless this is an XMC_XO symbol, we don't bother to actually
-        define it, since we don't have a section to put it in anyhow.
-        Instead, the relocation routines handle the DEF_DYNAMIC flag
-        correctly.  */
+      if (!xcoff_dynamic_definition_p (h, &ldsym))
+       continue;
 
-      if (h->smclas == XMC_XO
-         && (h->root.type == bfd_link_hash_undefined
-             || h->root.type == bfd_link_hash_undefweak))
+      h->flags |= XCOFF_DEF_DYNAMIC;
+      h->smclas = ldsym.l_smclas;
+      if (h->smclas == XMC_XO)
        {
          /* This symbol has an absolute value.  */
-         h->root.type = bfd_link_hash_defined;
+         if ((ldsym.l_smtype & L_WEAK) != 0)
+           h->root.type = bfd_link_hash_defweak;
+         else
+           h->root.type = bfd_link_hash_defined;
          h->root.u.def.section = bfd_abs_section_ptr;
          h->root.u.def.value = ldsym.l_value;
        }
+      else
+       {
+         /* Otherwise, we don't bother to actually define the symbol,
+            since we don't have a section to put it in anyhow.
+            We assume instead that an undefined XCOFF_DEF_DYNAMIC symbol
+            should be imported from the symbol's undef.abfd.  */
+         if ((ldsym.l_smtype & L_WEAK) != 0)
+           h->root.type = bfd_link_hash_undefweak;
+         else
+           h->root.type = bfd_link_hash_undefined;
+         h->root.u.undef.abfd = abfd;
+       }
 
       /* If this symbol defines a function descriptor, then it
         implicitly defines the function code as well.  */
@@ -701,33 +726,30 @@ xcoff_link_add_dynamic_symbols (bfd *abfd, struct bfd_link_info *info)
              if (hds == NULL)
                return FALSE;
 
-             if (hds->root.type == bfd_link_hash_new)
-               {
-                 hds->root.type = bfd_link_hash_undefined;
-                 hds->root.u.undef.abfd = abfd;
-                 /* We do not want to add this to the undefined
-                    symbol list.  */
-               }
-
              hds->descriptor = h;
              h->descriptor = hds;
            }
 
-         hds->flags |= XCOFF_DEF_DYNAMIC;
-         if (hds->smclas == XMC_UA)
-           hds->smclas = XMC_PR;
-
-         /* An absolute symbol appears to actually define code, not a
-            function descriptor.  This is how some math functions are
-            implemented on AIX 4.1.  */
-         if (h->smclas == XMC_XO
-             && (hds->root.type == bfd_link_hash_undefined
-                 || hds->root.type == bfd_link_hash_undefweak))
+         if (xcoff_dynamic_definition_p (hds, &ldsym))
            {
-             hds->smclas = XMC_XO;
-             hds->root.type = bfd_link_hash_defined;
-             hds->root.u.def.section = bfd_abs_section_ptr;
-             hds->root.u.def.value = ldsym.l_value;
+             hds->root.type = h->root.type;
+             hds->flags |= XCOFF_DEF_DYNAMIC;
+             if (h->smclas == XMC_XO)
+               {
+                 /* An absolute symbol appears to actually define code, not a
+                    function descriptor.  This is how some math functions are
+                    implemented on AIX 4.1.  */
+                 hds->smclas = XMC_XO;
+                 hds->root.u.def.section = bfd_abs_section_ptr;
+                 hds->root.u.def.value = ldsym.l_value;
+               }
+             else
+               {
+                 hds->smclas = XMC_PR;
+                 hds->root.u.undef.abfd = abfd;
+                 /* We do not want to add this to the undefined
+                    symbol list.  */
+               }
            }
        }
     }
@@ -1087,7 +1109,6 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
       const char *name;
       char buf[SYMNMLEN + 1];
       int smtyp;
-      flagword flags;
       asection *section;
       bfd_vma value;
       struct xcoff_link_hash_entry *set_toc;
@@ -1096,7 +1117,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 
       /* In this pass we are only interested in symbols with csect
         information.  */
-      if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
+      if (!CSECT_SYM_P (sym.n_sclass))
        {
          /* Set csect_cache,
             Normally csect is a .pr, .rw  etc. created in the loop
@@ -1216,7 +1237,6 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 
       smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
 
-      flags = BSF_GLOBAL;
       section = NULL;
       value = 0;
       set_toc = NULL;
@@ -1327,7 +1347,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                  erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
                             + rel->r_symndx * symesz);
                  bfd_coff_swap_sym_in (abfd, (void *) erelsym, (void *) &relsym);
-                 if (relsym.n_sclass == C_EXT)
+                 if (EXTERN_SYM_P (relsym.n_sclass))
                    {
                      const char *relname;
                      char relbuf[SYMNMLEN + 1];
@@ -1482,9 +1502,9 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
            if (first_csect == NULL)
              first_csect = csect;
 
-           /* If this symbol is C_EXT, we treat it as starting at the
+           /* If this symbol is external, we treat it as starting at the
               beginning of the newly created section.  */
-           if (sym.n_sclass == C_EXT)
+           if (EXTERN_SYM_P (sym.n_sclass))
              {
                section = csect;
                value = 0;
@@ -1573,7 +1593,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
          if (first_csect == NULL)
            first_csect = csect;
 
-         if (sym.n_sclass == C_EXT)
+         if (EXTERN_SYM_P (sym.n_sclass))
            {
              csect->flags |= SEC_IS_COMMON;
              csect->size = 0;
@@ -1614,9 +1634,10 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
       /* Now we have enough information to add the symbol to the
         linker hash table.  */
 
-      if (sym.n_sclass == C_EXT)
+      if (EXTERN_SYM_P (sym.n_sclass))
        {
          bfd_boolean copy;
+         flagword flags;
 
          BFD_ASSERT (section != NULL);
 
@@ -1687,8 +1708,8 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                      section = bfd_und_section_ptr;
                      value = 0;
                    }
-                 else if (((*sym_hash)->root.u.def.section->owner->flags
-                           & DYNAMIC) != 0)
+                 else if (((*sym_hash)->flags & XCOFF_DEF_REGULAR) == 0
+                          && ((*sym_hash)->flags & XCOFF_DEF_DYNAMIC) != 0)
                    {
                      /* The existing symbol is from a shared library.
                         Replace it.  */
@@ -1704,6 +1725,12 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                      section = bfd_und_section_ptr;
                      value = 0;
                    }
+                 else if (sym.n_sclass == C_AIX_WEAKEXT
+                          || (*sym_hash)->root.type == bfd_link_hash_defweak)
+                   {
+                     /* At least one of the definitions is weak.
+                        Allow the normal rules to take effect.  */
+                   }
                  else if ((*sym_hash)->root.u.undef.next != NULL
                           || info->hash->undefs_tail == &(*sym_hash)->root)
                    {
@@ -1723,8 +1750,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
                    }
                }
              else if (((*sym_hash)->flags & XCOFF_MULTIPLY_DEFINED) != 0
-                      && ((*sym_hash)->root.type == bfd_link_hash_defined
-                          || (*sym_hash)->root.type == bfd_link_hash_defweak)
+                      && (*sym_hash)->root.type == bfd_link_hash_defined
                       && (bfd_is_und_section (section)
                           || bfd_is_com_section (section)))
                {
@@ -1759,6 +1785,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
             a second time from the csects.  */
          BFD_ASSERT (last_real->next == first_csect);
          last_real->next = NULL;
+         flags = (sym.n_sclass == C_EXT ? BSF_GLOBAL : BSF_WEAK);
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, name, flags, section, value,
                  NULL, copy, TRUE,
@@ -2073,7 +2100,7 @@ xcoff_link_check_ar_symbols (bfd *abfd,
 
       bfd_coff_swap_sym_in (abfd, (void *) esym, (void *) &sym);
 
-      if (sym.n_sclass == C_EXT && sym.n_scnum != N_UNDEF)
+      if (EXTERN_SYM_P (sym.n_sclass) && sym.n_scnum != N_UNDEF)
        {
          const char *name;
          char buf[SYMNMLEN + 1];
@@ -2286,6 +2313,97 @@ xcoff_set_import_path (struct bfd_link_info *info,
   return TRUE;
 }
 \f
+/* Return true if the given bfd contains at least one shared object.  */
+
+static bfd_boolean
+xcoff_archive_contains_shared_object_p (bfd *archive)
+{
+  bfd *member;
+
+  member = bfd_openr_next_archived_file (archive, NULL);
+  while (member != NULL && (member->flags & DYNAMIC) == 0)
+    member = bfd_openr_next_archived_file (archive, member);
+  return member != NULL;
+}
+
+/* Symbol H qualifies for export by -bexpfull.  Return true if it also
+   qualifies for export by -bexpall.  */
+
+static bfd_boolean
+xcoff_covered_by_expall_p (struct xcoff_link_hash_entry *h)
+{
+  /* Exclude symbols beginning with '_'.  */
+  if (h->root.root.string[0] == '_')
+    return FALSE;
+
+  /* Exclude archive members that would otherwise be unreferenced.  */
+  if ((h->flags & XCOFF_MARK) == 0
+      && (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+      && h->root.u.def.section->owner != NULL
+      && h->root.u.def.section->owner->my_archive != NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Return true if symbol H qualifies for the forms of automatic export
+   specified by AUTO_EXPORT_FLAGS.  */
+
+static bfd_boolean
+xcoff_auto_export_p (struct xcoff_link_hash_entry *h,
+                    unsigned int auto_export_flags)
+{
+  /* Don't automatically export things that were explicitly exported.  */
+  if ((h->flags & XCOFF_EXPORT) != 0)
+    return FALSE;
+
+  /* Don't export things that we don't define.  */
+  if ((h->flags & XCOFF_DEF_REGULAR) == 0)
+    return FALSE;
+
+  /* Don't export functions; export their descriptors instead.  */
+  if (h->root.root.string[0] == '.')
+    return FALSE;
+
+  /* We don't export a symbol which is being defined by an object
+     included from an archive which contains a shared object.  The
+     rationale is that if an archive contains both an unshared and
+     a shared object, then there must be some reason that the
+     unshared object is unshared, and we don't want to start
+     providing a shared version of it.  In particular, this solves
+     a bug involving the _savefNN set of functions.  gcc will call
+     those functions without providing a slot to restore the TOC,
+     so it is essential that these functions be linked in directly
+     and not from a shared object, which means that a shared
+     object which also happens to link them in must not export
+     them.  This is confusing, but I haven't been able to think of
+     a different approach.  Note that the symbols can, of course,
+     be exported explicitly.  */
+  if (h->root.type == bfd_link_hash_defined
+      || h->root.type == bfd_link_hash_defweak)
+    {
+      bfd *owner;
+
+      owner = h->root.u.def.section->owner;
+      if (owner != NULL
+         && owner->my_archive != NULL
+         && xcoff_archive_contains_shared_object_p (owner->my_archive))
+       return FALSE;
+    }
+
+  /* Otherwise, all symbols are exported by -bexpfull.  */
+  if ((auto_export_flags & XCOFF_EXPFULL) != 0)
+    return TRUE;
+
+  /* Despite its name, -bexpall exports most but not all symbols.  */
+  if ((auto_export_flags & XCOFF_EXPALL) != 0
+      && xcoff_covered_by_expall_p (h))
+    return TRUE;
+
+  return FALSE;
+}
+\f
 /* Mark a symbol as not being garbage, including the section in which
    it is defined.  */
 
@@ -2455,6 +2573,30 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
   return TRUE;
 }
 
+/* Look for a symbol called NAME.  If the symbol is defined, mark it.
+   If the symbol exists, set FLAGS.  */
+
+static bfd_boolean
+xcoff_mark_symbol_by_name (struct bfd_link_info *info,
+                          const char *name, unsigned int flags)
+{
+  struct xcoff_link_hash_entry *h;
+
+  h = xcoff_link_hash_lookup (xcoff_hash_table (info), name,
+                             FALSE, FALSE, TRUE);
+  if (h != NULL)
+    {
+      h->flags |= flags;
+      if (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+       {
+         if (!xcoff_mark (info, h->root.u.def.section))
+           return FALSE;
+       }
+    }
+  return TRUE;
+}
+
 /* The mark phase of garbage collection.  For a given section, mark
    it, and all the sections which define symbols to which it refers.
    Because this function needs to look at the relocs, we also count
@@ -2504,7 +2646,6 @@ xcoff_mark (struct bfd_link_info *info, asection *sec)
          relend = rel + sec->reloc_count;
          for (; rel < relend; rel++)
            {
-             asection *rsec;
              struct xcoff_link_hash_entry *h;
 
              if ((unsigned int) rel->r_symndx
@@ -2512,21 +2653,25 @@ xcoff_mark (struct bfd_link_info *info, asection *sec)
                continue;
 
              h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
-             if (h != NULL
-                 && (h->flags & XCOFF_MARK) == 0)
+             if (h != NULL)
                {
-                 if (! xcoff_mark_symbol (info, h))
-                   return FALSE;
+                 if ((h->flags & XCOFF_MARK) == 0)
+                   {
+                     if (!xcoff_mark_symbol (info, h))
+                       return FALSE;
+                   }
                }
-
-             rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
-             if (rsec != NULL
-                 && !bfd_is_und_section (rsec)
-                 && !bfd_is_abs_section (rsec)
-                 && (rsec->flags & SEC_MARK) == 0)
+             else
                {
-                 if (! xcoff_mark (info, rsec))
-                   return FALSE;
+                 asection *rsec;
+
+                 rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
+                 if (rsec != NULL
+                     && (rsec->flags & SEC_MARK) == 0)
+                   {
+                     if (!xcoff_mark (info, rsec))
+                       return FALSE;
+                   }
                }
 
              /* See if this reloc needs to be copied into the .loader
@@ -2824,8 +2969,56 @@ bfd_xcoff_record_link_assignment (bfd *output_bfd,
   return TRUE;
 }
 
+/* An xcoff_link_hash_traverse callback for which DATA points to an
+   xcoff_loader_info.  Mark all symbols that should be automatically
+   exported.  */
+
+static bfd_boolean
+xcoff_mark_auto_exports (struct xcoff_link_hash_entry *h, void *data)
+{
+  struct xcoff_loader_info *ldinfo;
+
+  ldinfo = (struct xcoff_loader_info *) data;
+  if (xcoff_auto_export_p (h, ldinfo->auto_export_flags))
+    {
+      if (!xcoff_mark_symbol (ldinfo->info, h))
+       ldinfo->failed = TRUE;
+    }
+  return TRUE;
+}
+
 /* Add a symbol to the .loader symbols, if necessary.  */
 
+/* INPUT_BFD has an external symbol associated with hash table entry H
+   and csect CSECT.   Return true if INPUT_BFD defines H.  */
+
+static bfd_boolean
+xcoff_final_definition_p (bfd *input_bfd, struct xcoff_link_hash_entry *h,
+                         asection *csect)
+{
+  switch (h->root.type)
+    {
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+      /* No input bfd owns absolute symbols.  They are written by
+        xcoff_write_global_symbol instead.  */
+      return (!bfd_is_abs_section (csect)
+             && h->root.u.def.section == csect);
+
+    case bfd_link_hash_common:
+      return h->root.u.c.p->section->owner == input_bfd;
+
+    case bfd_link_hash_undefined:
+    case bfd_link_hash_undefweak:
+      /* We can't treat undef.abfd as the owner because that bfd
+        might be a dynamic object.  Allow any bfd to claim it.  */
+      return TRUE;
+
+    default:
+      abort ();
+    }
+}
+
 static bfd_boolean
 xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
 {
@@ -2855,50 +3048,8 @@ xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
   /* If all defined symbols should be exported, mark them now.  We
      don't want to export the actual functions, just the function
      descriptors.  */
-  if (ldinfo->export_defineds
-      && (h->flags & XCOFF_DEF_REGULAR) != 0
-      && h->root.root.string[0] != '.')
-    {
-      bfd_boolean export;
-
-      /* We don't export a symbol which is being defined by an object
-        included from an archive which contains a shared object.  The
-        rationale is that if an archive contains both an unshared and
-        a shared object, then there must be some reason that the
-        unshared object is unshared, and we don't want to start
-        providing a shared version of it.  In particular, this solves
-        a bug involving the _savefNN set of functions.  gcc will call
-        those functions without providing a slot to restore the TOC,
-        so it is essential that these functions be linked in directly
-        and not from a shared object, which means that a shared
-        object which also happens to link them in must not export
-        them.  This is confusing, but I haven't been able to think of
-        a different approach.  Note that the symbols can, of course,
-        be exported explicitly.  */
-      export = TRUE;
-      if ((h->root.type == bfd_link_hash_defined
-          || h->root.type == bfd_link_hash_defweak)
-         && h->root.u.def.section->owner != NULL
-         && h->root.u.def.section->owner->my_archive != NULL)
-       {
-         bfd *arbfd, *member;
-
-         arbfd = h->root.u.def.section->owner->my_archive;
-         member = bfd_openr_next_archived_file (arbfd, NULL);
-         while (member != NULL)
-           {
-             if ((member->flags & DYNAMIC) != 0)
-               {
-                 export = FALSE;
-                 break;
-               }
-             member = bfd_openr_next_archived_file (arbfd, member);
-           }
-       }
-
-      if (export)
-       h->flags |= XCOFF_EXPORT;
-    }
+  if (xcoff_auto_export_p (h, ldinfo->auto_export_flags))
+    h->flags |= XCOFF_EXPORT;
 
   /* We don't want to garbage collect symbols which are not defined in
      XCOFF files.  This is a convenient place to mark them.  */
@@ -3036,25 +3187,19 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
   if (info->strip == strip_all)
     return 0;
 
-  /* We can ignore external references that were resolved by the link.  */
-  smtyp = SMTYP_SMTYP (aux->x_csect.x_smtyp);
-  if (isym->n_sclass == C_EXT
-      && smtyp == XTY_ER
-      && h->root.type != bfd_link_hash_undefined)
-    return 0;
-
-  /* We can ignore common symbols if they got defined somewhere else.  */
-  if (isym->n_sclass == C_EXT
-      && smtyp == XTY_CM
-      && (h->root.type != bfd_link_hash_common
-         || h->root.u.c.p->section != csect)
-      && (h->root.type != bfd_link_hash_defined
-         || h->root.u.def.section != csect))
-    return 0;
+  /* Discard symbols that are defined elsewhere.  */
+  if (EXTERN_SYM_P (isym->n_sclass))
+    {
+      if ((h->flags & XCOFF_ALLOCATED) != 0)
+       return 0;
+      if (!xcoff_final_definition_p (input_bfd, h, csect))
+       return 0;
+    }
 
   /* If we're discarding local symbols, check whether ISYM is local.  */
+  smtyp = SMTYP_SMTYP (aux->x_csect.x_smtyp);
   if (info->discard == discard_all
-      && isym->n_sclass != C_EXT
+      && !EXTERN_SYM_P (isym->n_sclass)
       && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD))
     return 0;
 
@@ -3082,7 +3227,7 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
        return 0;
 
       if (info->discard == discard_l
-         && isym->n_sclass != C_EXT
+         && !EXTERN_SYM_P (isym->n_sclass)
          && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD)
          && bfd_is_local_label_name (input_bfd, name))
        return 0;
@@ -3103,10 +3248,9 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
    -bmaxdata linker option).  GC is whether to do garbage collection
    (the -bgc linker option).  MODTYPE is the module type (the
    -bmodtype linker option).  TEXTRO is whether the text section must
-   be read only (the -btextro linker option).  EXPORT_DEFINEDS is
-   whether all defined symbols should be exported (the -unix linker
-   option).  SPECIAL_SECTIONS is set by this routine to csects with
-   magic names like _end.  */
+   be read only (the -btextro linker option).  AUTO_EXPORT_FLAGS
+   is a mask of XCOFF_EXPALL and XCOFF_EXPFULL.  SPECIAL_SECTIONS
+   is set by this routine to csects with magic names like _end.  */
 
 bfd_boolean
 bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
@@ -3119,11 +3263,10 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
                                 bfd_boolean gc,
                                 int modtype,
                                 bfd_boolean textro,
-                                bfd_boolean export_defineds,
+                                unsigned int auto_export_flags,
                                 asection **special_sections,
                                 bfd_boolean rtld)
 {
-  struct xcoff_link_hash_entry *hentry;
   asection *lsec;
   struct xcoff_loader_info ldinfo;
   int i;
@@ -3148,7 +3291,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
   ldinfo.failed = FALSE;
   ldinfo.output_bfd = output_bfd;
   ldinfo.info = info;
-  ldinfo.export_defineds = export_defineds;
+  ldinfo.auto_export_flags = auto_export_flags;
   ldinfo.ldsym_count = 0;
   ldinfo.string_size = 0;
   ldinfo.strings = NULL;
@@ -3162,15 +3305,6 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
   xcoff_hash_table (info)->textro = textro;
   xcoff_hash_table (info)->rtld = rtld;
 
-  hentry = NULL;
-  if (entry != NULL)
-    {
-      hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
-                                      FALSE, FALSE, TRUE);
-      if (hentry != NULL)
-       hentry->flags |= XCOFF_ENTRY;
-    }
-
   /* __rtinit */
   if (info->init_function || info->fini_function || rtld)
     {
@@ -3223,11 +3357,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
     }
 
   /* Garbage collect unused sections.  */
-  if (info->relocatable
-      || ! gc
-      || hentry == NULL
-      || (hentry->root.type != bfd_link_hash_defined
-         && hentry->root.type != bfd_link_hash_defweak))
+  if (info->relocatable || !gc)
     {
       gc = FALSE;
       xcoff_hash_table (info)->gc = FALSE;
@@ -3255,8 +3385,22 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
     }
   else
     {
-      if (! xcoff_mark (info, hentry->root.u.def.section))
+      if (entry != NULL
+         && !xcoff_mark_symbol_by_name (info, entry, XCOFF_ENTRY))
+       goto error_return;
+      if (info->init_function != NULL
+         && !xcoff_mark_symbol_by_name (info, info->init_function, 0))
        goto error_return;
+      if (info->fini_function != NULL
+         && !xcoff_mark_symbol_by_name (info, info->fini_function, 0))
+       goto error_return;
+      if (auto_export_flags != 0)
+       {
+         xcoff_link_hash_traverse (xcoff_hash_table (info),
+                                   xcoff_mark_auto_exports, &ldinfo);
+         if (ldinfo.failed)
+           goto error_return;
+       }
       xcoff_sweep (info);
       xcoff_hash_table (info)->gc = TRUE;
     }
@@ -3468,9 +3612,8 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
 
          bfd_coff_swap_sym_in (sub, esym, &sym);
 
-         /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
-            information too.  */
-         if (sym.n_sclass == C_EXT || sym.n_sclass == C_HIDEXT)
+         /* Read in the csect information, if any.  */
+         if (CSECT_SYM_P (sym.n_sclass))
            {
              BFD_ASSERT (sym.n_numaux > 0);
              bfd_coff_swap_aux_in (sub, esym + symesz * sym.n_numaux,
@@ -3513,6 +3656,8 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
                }
              else
                *debug_index = -1;
+             if (*sym_hash != 0)
+               (*sym_hash)->flags |= XCOFF_ALLOCATED;
              if (*lineno_counts > 0)
                csect->output_section->lineno_count += *lineno_counts;
            }
@@ -3669,9 +3814,8 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
 
       bfd_coff_swap_sym_in (input_bfd, (void *) esym, (void *) isymp);
 
-      /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
-        information.  */
-      if (isymp->n_sclass == C_EXT || isymp->n_sclass == C_HIDEXT)
+      /* Read in the csect information, if any.  */
+      if (CSECT_SYM_P (isymp->n_sclass))
        {
          BFD_ASSERT (isymp->n_numaux > 0);
          bfd_coff_swap_aux_in (input_bfd,
@@ -3687,11 +3831,10 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
         .loader symbol information.  If this is an external symbol
         reference to a defined symbol, though, then wait until we get
         to the definition.  */
-      if (isymp->n_sclass == C_EXT
+      if (EXTERN_SYM_P (isymp->n_sclass)
          && *sym_hash != NULL
          && (*sym_hash)->ldsym != NULL
-         && (smtyp != XTY_ER
-             || (*sym_hash)->root.type == bfd_link_hash_undefined))
+         && xcoff_final_definition_p (input_bfd, *sym_hash, *csectpp))
        {
          struct xcoff_link_hash_entry *h;
          struct internal_ldsym *ldsym;
@@ -3723,6 +3866,8 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
            ldsym->l_smtype |= L_EXPORT;
          if ((h->flags & XCOFF_ENTRY) != 0)
            ldsym->l_smtype |= L_ENTRY;
+         if (isymp->n_sclass == C_AIX_WEAKEXT)
+           ldsym->l_smtype |= L_WEAK;
 
          ldsym->l_smclas = aux.x_csect.x_smclas;
 
@@ -3784,7 +3929,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
          /* Assign the next unused index to this symbol.  */
          *indexp = output_index;
 
-         if (isymp->n_sclass == C_EXT)
+         if (EXTERN_SYM_P (isymp->n_sclass))
            {
              BFD_ASSERT (*sym_hash != NULL);
              (*sym_hash)->indx = output_index;
@@ -3990,8 +4135,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
                      aux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
                    }
                }
-             else if ((isymp->n_sclass == C_EXT
-                       || isymp->n_sclass == C_HIDEXT)
+             else if (CSECT_SYM_P (isymp->n_sclass)
                       && i + 1 == isymp->n_numaux)
                {
 
@@ -4070,8 +4214,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
              /* Copy over the line numbers, unless we are stripping
                 them.  We do this on a symbol by symbol basis in
                 order to more easily handle garbage collection.  */
-             if ((isymp->n_sclass == C_EXT
-                  || isymp->n_sclass == C_HIDEXT)
+             if (CSECT_SYM_P (isymp->n_sclass)
                  && i == 0
                  && isymp->n_numaux > 1
                  && ISFCN (isymp->n_type)
@@ -5166,7 +5309,11 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
     {
       isym.n_value = 0;
       isym.n_scnum = N_UNDEF;
-      isym.n_sclass = C_EXT;
+      if (h->root.type == bfd_link_hash_undefweak
+         && C_WEAKEXT == C_AIX_WEAKEXT)
+       isym.n_sclass = C_WEAKEXT;
+      else
+       isym.n_sclass = C_EXT;
       aux.x_csect.x_smtyp = XTY_ER;
     }
   else if ((h->root.type == bfd_link_hash_defined
@@ -5176,7 +5323,11 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
       BFD_ASSERT (bfd_is_abs_section (h->root.u.def.section));
       isym.n_value = h->root.u.def.value;
       isym.n_scnum = N_UNDEF;
-      isym.n_sclass = C_EXT;
+      if (h->root.type == bfd_link_hash_undefweak
+         && C_WEAKEXT == C_AIX_WEAKEXT)
+       isym.n_sclass = C_WEAKEXT;
+      else
+       isym.n_sclass = C_EXT;
       aux.x_csect.x_smtyp = XTY_ER;
     }
   else if (h->root.type == bfd_link_hash_defined
@@ -5238,7 +5389,11 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
       /* We just output an SD symbol.  Now output an LD symbol.  */
       h->indx += 2;
 
-      isym.n_sclass = C_EXT;
+      if (h->root.type == bfd_link_hash_undefweak
+         && C_WEAKEXT == C_AIX_WEAKEXT)
+       isym.n_sclass = C_WEAKEXT;
+      else
+       isym.n_sclass = C_EXT;
       bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
       outsym += bfd_coff_symesz (output_bfd);
 
This page took 0.032678 seconds and 4 git commands to generate.