From Robin Kirkham <Robin.Kirkham@mlb.dmt.csiro.au>:
[deliverable/binutils-gdb.git] / bfd / sunos.c
index e0c7a88656dfcf52e3a01871541124cab6b5c301..75f3ce3f63f98f01679eb876e4c79a93581b46d3 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD backend for SunOS binaries.
-   Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -78,6 +78,14 @@ static boolean sunos_finish_dynamic_link
 #define MY_check_dynamic_reloc sunos_check_dynamic_reloc
 #define MY_finish_dynamic_link sunos_finish_dynamic_link
 
+/* ??? Where should this go?  */
+#define MACHTYPE_OK(mtype) \
+  (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
+   || ((mtype) == M_SPARCLET \
+       && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
+   || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
+       && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
+
 /* Include the usual a.out support.  */
 #include "aoutf1.h"
 
@@ -620,9 +628,11 @@ struct sunos_link_hash_entry
   /* Symbol is defined by a regular object.  */
 #define SUNOS_DEF_REGULAR 02
   /* Symbol is referenced by a dynamic object.  */
-#define SUNOS_REF_DYNAMIC 010
+#define SUNOS_REF_DYNAMIC 04
   /* Symbol is defined by a dynamic object.  */
-#define SUNOS_DEF_DYNAMIC 020
+#define SUNOS_DEF_DYNAMIC 010
+  /* Symbol is a constructor symbol in a regular object.  */
+#define SUNOS_CONSTRUCTOR 020
 };
 
 /* The SunOS linker hash table.  */
@@ -1026,8 +1036,13 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
        return false;
     }
 
-  h = sunos_link_hash_lookup (sunos_hash_table (info), name, true, copy,
-                             false);
+  if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0
+      || ! bfd_is_und_section (section))
+    h = sunos_link_hash_lookup (sunos_hash_table (info), name, true, copy,
+                               false);
+  else
+    h = ((struct sunos_link_hash_entry *)
+        bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false));
   if (h == NULL)
     return false;
 
@@ -1077,6 +1092,29 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
        }
     }
 
+  if ((abfd->flags & DYNAMIC) != 0
+      && abfd->xvec == info->hash->creator
+      && (h->flags & SUNOS_CONSTRUCTOR) != 0)
+    {
+      /* The existing symbol is a constructor symbol, and this symbol
+         is from a dynamic object.  A constructor symbol is actually a
+         definition, although the type will be bfd_link_hash_undefined
+         at this point.  We want to ignore the definition from the
+         dynamic object.  */
+      section = bfd_und_section_ptr;
+    }
+  else if ((flags & BSF_CONSTRUCTOR) != 0
+          && (abfd->flags & DYNAMIC) == 0
+          && h->root.root.type == bfd_link_hash_defined
+          && h->root.root.u.def.section->owner != NULL
+          && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
+    {
+      /* The existing symbol is defined by a dynamic object, and this
+         is a constructor symbol.  As above, we want to force the use
+         of the constructor symbol from the regular object.  */
+      h->root.root.type = bfd_link_hash_new;
+    }
+
   /* Do the usual procedure for adding a symbol.  */
   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
                                          value, string, copy, collect,
@@ -1112,6 +1150,10 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
          ++sunos_hash_table (info)->dynsymcount;
          h->dynindx = -2;
        }
+
+      if ((flags & BSF_CONSTRUCTOR) != 0
+         && (abfd->flags & DYNAMIC) == 0)
+       h->flags |= SUNOS_CONSTRUCTOR;
     }
 
   return true;
@@ -1767,6 +1809,17 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
              || (h->flags & SUNOS_DEF_REGULAR) != 0))
        continue;
 
+      if (r_type == RELOC_JMP_TBL
+         && ! info->shared
+         && (h->flags & SUNOS_DEF_DYNAMIC) == 0
+         && (h->flags & SUNOS_DEF_REGULAR) == 0)
+       {
+         /* This symbol is apparently undefined.  Don't do anything
+             here; just let the relocation routine report an undefined
+             symbol.  */
+         continue;
+       }
+
       if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
        continue;
 
This page took 0.024701 seconds and 4 git commands to generate.