* elflink.c (_bfd_elf_dynamic_symbol_p): New.
authorRichard Henderson <rth@redhat.com>
Fri, 18 Jul 2003 21:09:28 +0000 (21:09 +0000)
committerRichard Henderson <rth@redhat.com>
Fri, 18 Jul 2003 21:09:28 +0000 (21:09 +0000)
        * elf-bfd.h (_bfd_elf_dynamic_symbol_p): Declare it.
        (SYMBOL_REFERENCES_LOCAL, SYMBOL_CALLS_LOCAL): Use it.
        * elf32-xtensa.c (xtensa_elf_dynamic_symbol_p): Likewise.
        * elf64-alpha.c (alpha_elf_dynamic_symbol_p): Likewise.
        * elf64-hppa.c (elf64_hppa_dynamic_symbol_p): Likewise.
        * elfxx-ia64.c (elfNN_ia64_dynamic_symbol_p): Likewise.
        Update all callers to provide the relocation being resolved.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-xtensa.c
bfd/elf64-alpha.c
bfd/elf64-hppa.c
bfd/elflink.c
bfd/elfxx-ia64.c

index f53db4d586a5f559c082545379721f1fe1f8fe62..adb20cfa582c43df99e3271e47f81c2bf5288688 100644 (file)
@@ -1,3 +1,14 @@
+2003-07-18  Richard Henderson  <rth@redhat.com>
+
+       * elflink.c (_bfd_elf_dynamic_symbol_p): New.
+       * elf-bfd.h (_bfd_elf_dynamic_symbol_p): Declare it.
+       (SYMBOL_REFERENCES_LOCAL, SYMBOL_CALLS_LOCAL): Use it.
+       * elf32-xtensa.c (xtensa_elf_dynamic_symbol_p): Likewise.
+       * elf64-alpha.c (alpha_elf_dynamic_symbol_p): Likewise.
+       * elf64-hppa.c (elf64_hppa_dynamic_symbol_p): Likewise.
+       * elfxx-ia64.c (elfNN_ia64_dynamic_symbol_p): Likewise.
+       Update all callers to provide the relocation being resolved.
+
 2003-07-17  Shaun Jackman <sjackman@pathwayconnect.com>
 
        * config.bfd (arm-wince-pe): Add -DARM_COFF_BUGFIX to
index b118524a8346384014b85fb833e5201ec48a5251..7d154fc735cf859904f5f228631bfaacdb15e6d4 100644 (file)
@@ -211,23 +211,12 @@ struct elf_link_hash_entry
    function symbols not defined in an app are set to their .plt entry,
    it's necessary for shared libs to also reference the .plt even
    though the symbol is really local to the shared lib.  */
-#define SYMBOL_REFERENCES_LOCAL(INFO, H)                               \
-  (((INFO)->executable                                                 \
-    || (INFO)->symbolic                                                        \
-    || (H)->dynindx == -1                                              \
-    || ELF_ST_VISIBILITY ((H)->other) == STV_INTERNAL                  \
-    || ELF_ST_VISIBILITY ((H)->other) == STV_HIDDEN                    \
-    || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)                \
-   && ((H)->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+#define SYMBOL_REFERENCES_LOCAL(INFO, H) \
+  _bfd_elf_dynamic_symbol_p (H, INFO, 1)
 
 /* Will _calls_ to this symbol always call the version in this object?  */
-#define SYMBOL_CALLS_LOCAL(INFO, H)                                    \
-  (((INFO)->executable                                                 \
-    || (INFO)->symbolic                                                        \
-    || (H)->dynindx == -1                                              \
-    || ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT                   \
-    || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)                \
-   && ((H)->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+#define SYMBOL_CALLS_LOCAL(INFO, H) \
+  _bfd_elf_dynamic_symbol_p (H, INFO, 0)
 
 /* Records local symbols to be emitted in the dynamic symbol table.  */
 
@@ -1506,6 +1495,9 @@ extern bfd_boolean _bfd_elf_adjust_dynamic_symbol
 extern bfd_boolean _bfd_elf_link_sec_merge_syms
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
+extern bfd_boolean _bfd_elf_dynamic_symbol_p
+  PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean));
+
 extern const bfd_target *bfd_elf32_object_p
   PARAMS ((bfd *));
 extern const bfd_target *bfd_elf32_core_file_p
index f68f342bf4f80e1a316353c658c69055750d1ef8..867832f08605536997c774e96fcb2dd80f137690 100644 (file)
@@ -1838,38 +1838,9 @@ xtensa_elf_dynamic_symbol_p (info, h)
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
 {
-  if (h == NULL)
-    return FALSE;
-
-  while (h->root.type == bfd_link_hash_indirect
-        || h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-  if (h->dynindx == -1)
-    return FALSE;
-
-  if (h->root.type == bfd_link_hash_undefweak
-      || h->root.type == bfd_link_hash_defweak)
-    return TRUE;
-
-  switch (ELF_ST_VISIBILITY (h->other))
-    {
-    case STV_DEFAULT:
-      break;
-    case STV_HIDDEN:
-    case STV_INTERNAL:
-      return FALSE;
-    case STV_PROTECTED:
-      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
-        return FALSE;
-      break;
-    }
-
-  if ((info->shared && !info->symbolic)
-      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    return TRUE;
-
-  return FALSE;
+  /* ??? What, if anything, needs to happen wrt STV_PROTECTED and PLT
+     entries?  For now assume the worst.  */
+  return _bfd_elf_dynamic_symbol_p (h, info, 1);
 }
 
 
index ca3aa194bf77ba1bc40788b3f77cbd2c346d954b..625b24398a68391c23aa0fc87370b71fec1722b9 100644 (file)
@@ -47,7 +47,7 @@
 #define ECOFF_64
 #include "ecoffswap.h"
 
-static int alpha_elf_dynamic_symbol_p
+static bfd_boolean alpha_elf_dynamic_symbol_p
   PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
 static struct bfd_hash_entry * elf64_alpha_link_hash_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
@@ -269,49 +269,17 @@ struct alpha_elf_link_hash_table
 #define alpha_elf_sym_hashes(abfd) \
   ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
 
-/* Should we do dynamic things to this symbol?  */
+/* Should we do dynamic things to this symbol?  This differs from the 
+   generic version in that we never need to consider function pointer
+   equality wrt PLT entries -- we don't create a PLT entry if a symbol's
+   address is ever taken.  */
 
-static int
+static inline bfd_boolean
 alpha_elf_dynamic_symbol_p (h, info)
      struct elf_link_hash_entry *h;
      struct bfd_link_info *info;
 {
-  if (h == NULL)
-    return FALSE;
-
-  while (h->root.type == bfd_link_hash_indirect
-        || h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-  if (h->dynindx == -1)
-    return FALSE;
-
-  if (h->root.type == bfd_link_hash_undefweak
-      || h->root.type == bfd_link_hash_defweak)
-    return TRUE;
-
-  switch (ELF_ST_VISIBILITY (h->other))
-    {
-    case STV_DEFAULT:
-      break;
-    case STV_HIDDEN:
-    case STV_INTERNAL:
-      return FALSE;
-    case STV_PROTECTED:
-      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
-        return FALSE;
-      break;
-    }
-
-  if ((info->shared && !info->symbolic)
-      || ((h->elf_link_hash_flags
-          & (ELF_LINK_HASH_DEF_DYNAMIC
-             | ELF_LINK_HASH_DEF_REGULAR
-             | ELF_LINK_HASH_REF_REGULAR))
-         == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
-    return TRUE;
-
-  return FALSE;
+  return _bfd_elf_dynamic_symbol_p (h, info, 0);
 }
 
 /* Create an entry in a Alpha ELF linker hash table.  */
index 4c88a543a37560a41fa3da8d545d7724e1210e1f..2cee551d6b66b56583074642edb14fcc05fbc378 100644 (file)
@@ -956,30 +956,19 @@ elf64_hppa_dynamic_symbol_p (h, info)
      struct elf_link_hash_entry *h;
      struct bfd_link_info *info;
 {
-  if (h == NULL)
-    return FALSE;
-
-  while (h->root.type == bfd_link_hash_indirect
-        || h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-  if (h->dynindx == -1)
-    return FALSE;
-
-  if (h->root.type == bfd_link_hash_undefweak
-      || h->root.type == bfd_link_hash_defweak)
-    return TRUE;
+  /* ??? What, if anything, needs to happen wrt STV_PROTECTED symbols
+     and relocations that retrieve a function descriptor?  Assume the
+     worst for now.  */
+  if (_bfd_elf_dynamic_symbol_p (h, info, 1))
+    {
+      /* ??? Why is this here and not elsewhere is_local_label_name.  */
+      if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$')
+       return FALSE;
 
-  if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$')
+      return TRUE;
+    }
+  else
     return FALSE;
-
-  if ((info->shared && (!info->symbolic || info->allow_shlib_undefined))
-      || ((h->elf_link_hash_flags
-          & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
-         == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
-    return TRUE;
-
-  return FALSE;
 }
 
 /* Mark all funtions exported by this file so that we can later allocate
index b448367d24eb627dc21d61501145121d34141522..2fd588ae1101c2873d09d79386037780494b32a8 100644 (file)
@@ -2474,3 +2474,63 @@ _bfd_elf_link_sec_merge_syms (h, data)
 
   return TRUE;
 }
+
+/* Returns false if the symbol referred to by H should be considered
+   to resolve local to the current module, and true if it should be
+   considered to bind dynamically.  */
+
+bfd_boolean
+_bfd_elf_dynamic_symbol_p (h, info, ignore_protected)
+     struct elf_link_hash_entry *h;
+     struct bfd_link_info *info;
+     bfd_boolean ignore_protected;
+{
+  bfd_boolean binding_stays_local_p;
+
+  if (h == NULL)
+    return FALSE;
+
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  /* If it was forced local, then clearly it's not dynamic.  */
+  if (h->dynindx == -1)
+    return FALSE;
+  if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
+    return FALSE;
+
+  /* Identify the cases where name binding rules say that a
+     visible symbol resolves locally.  */
+  binding_stays_local_p = info->executable || info->symbolic;
+
+  switch (ELF_ST_VISIBILITY (h->other))
+    {
+    case STV_INTERNAL:
+    case STV_HIDDEN:
+      return FALSE;
+
+    case STV_PROTECTED:
+      /* Proper resolution for function pointer equality may require
+        that these symbols perhaps be resolved dynamically, even though
+        we should be resolving them to the current module.  */
+      if (!ignore_protected)
+       binding_stays_local_p = TRUE;
+      break;
+
+    default:
+      /* With STV_DEFAULT, weak symbols do not bind locally.  */
+      if (h->root.type == bfd_link_hash_undefweak
+          || h->root.type == bfd_link_hash_defweak)
+       return TRUE;
+      break;
+    }
+
+  /* If it isn't defined locally, then clearly it's dynamic.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    return TRUE;
+
+  /* Otherwise, the symbol is dynamic if binding rules don't tell
+     us that it remains local.  */
+  return !binding_stays_local_p;
+}
index f98e4ee188d10f1c8bf241b8249a117ea4930d88..a061e7d052f11b9023aad43349528c4fc4afa388 100644 (file)
@@ -200,7 +200,7 @@ static bfd_boolean elfNN_ia64_modify_segment_map
 static bfd_boolean elfNN_ia64_is_local_label_name
   PARAMS ((bfd *abfd, const char *name));
 static bfd_boolean elfNN_ia64_dynamic_symbol_p
-  PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info));
+  PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
 static bfd_boolean elfNN_ia64_local_hash_table_init
   PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd,
           new_hash_entry_func new));
@@ -831,7 +831,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
            }
 
          /* Can't do anything else with dynamic symbols.  */
-         else if (elfNN_ia64_dynamic_symbol_p (h, link_info))
+         else if (elfNN_ia64_dynamic_symbol_p (h, link_info, r_type))
            continue;
 
          else
@@ -1508,38 +1508,16 @@ elfNN_ia64_is_local_label_name (abfd, name)
 /* Should we do dynamic things to this symbol?  */
 
 static bfd_boolean
-elfNN_ia64_dynamic_symbol_p (h, info)
+elfNN_ia64_dynamic_symbol_p (h, info, r_type)
      struct elf_link_hash_entry *h;
      struct bfd_link_info *info;
+     int r_type;
 {
-  if (h == NULL)
-    return FALSE;
-
-  while (h->root.type == bfd_link_hash_indirect
-        || h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  bfd_boolean ignore_protected
+    = ((r_type & 0xf8) == 0x40         /* FPTR relocs */
+       || (r_type & 0xf8) == 0x50);    /* LTOFF_FPTR relocs */
 
-  if (h->dynindx == -1)
-    return FALSE;
-  switch (ELF_ST_VISIBILITY (h->other))
-    {
-    case STV_INTERNAL:
-    case STV_HIDDEN:
-      return FALSE;
-    default:
-      break;
-    }
-
-  if (h->root.type == bfd_link_hash_undefweak
-      || h->root.type == bfd_link_hash_defweak)
-    return TRUE;
-
-  /* If it isn't defined locally, then clearly it's dynamic.  */
-  if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    return TRUE;
-
-  /* Identify the cases where name binding rules say it resolves local.  */
-  return !(info->executable || info->symbolic);
+  return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected);
 }
 \f
 static bfd_boolean
@@ -2415,7 +2393,7 @@ allocate_global_data_got (dyn_i, data)
 
   if ((dyn_i->want_got || dyn_i->want_gotx)
       && ! dyn_i->want_fptr
-      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
      {
        dyn_i->got_offset = x->ofs;
        x->ofs += 8;
@@ -2427,7 +2405,7 @@ allocate_global_data_got (dyn_i, data)
     }
   if (dyn_i->want_dtpmod)
     {
-      if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
        {
          dyn_i->dtpmod_offset = x->ofs;
          x->ofs += 8;
@@ -2464,7 +2442,7 @@ allocate_global_fptr_got (dyn_i, data)
 
   if (dyn_i->want_got
       && dyn_i->want_fptr
-      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, R_IA64_FPTR64LSB))
     {
       dyn_i->got_offset = x->ofs;
       x->ofs += 8;
@@ -2482,7 +2460,7 @@ allocate_local_got (dyn_i, data)
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
   if ((dyn_i->want_got || dyn_i->want_gotx)
-      && !elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      && !elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0))
     {
       dyn_i->got_offset = x->ofs;
       x->ofs += 8;
@@ -2576,7 +2554,7 @@ allocate_plt_entries (dyn_i, data)
          h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
       /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT.  */
-      if (elfNN_ia64_dynamic_symbol_p (h, x->info))
+      if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0))
        {
          bfd_size_type offset = x->ofs;
          if (offset == 0)
@@ -2654,7 +2632,10 @@ allocate_dynrel_entries (dyn_i, data)
   bfd_boolean dynamic_symbol, shared, resolved_zero;
 
   ia64_info = elfNN_ia64_hash_table (x->info);
-  dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info);
+
+  /* Note that this can't be used in relation to FPTR relocs below.  */
+  dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0);
+
   shared = x->info->shared;
   resolved_zero = (dyn_i->h
                   && ELF_ST_VISIBILITY (dyn_i->h->other)
@@ -3342,7 +3323,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
                || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
                || dyn_i->h->root.type != bfd_link_hash_undefweak)
            && dyn_r_type != R_IA64_DTPREL64LSB)
-           || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
+           || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type)
           || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
          && (!dyn_i->want_ltoff_fptr
              || !info->pie
@@ -3807,7 +3788,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
       asection *sym_sec;
       bfd_byte *hit_addr;
       bfd_boolean dynamic_symbol_p;
-      bfd_boolean local_symbol_p;
       bfd_boolean undef_weak_ref;
 
       r_type = ELFNN_R_TYPE (rel->r_info);
@@ -3918,12 +3898,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
       hit_addr = contents + rel->r_offset;
       value += rel->r_addend;
-      dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info);
-      /* Is this symbol locally defined? A protected symbol is locallly
-        defined. But its function descriptor may not. Use it with
-        caution.  */
-      local_symbol_p = (! dynamic_symbol_p
-                       || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT);
+      dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type);
 
       switch (r_type)
        {
@@ -3952,7 +3927,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
              /* If we don't need dynamic symbol lookup, find a
                 matching RELATIVE relocation.  */
              dyn_r_type = r_type;
-             if (! local_symbol_p)
+             if (dynamic_symbol_p)
                {
                  dynindx = h->dynindx;
                  addend = rel->r_addend;
@@ -4300,7 +4275,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
              /* If we don't need dynamic symbol lookup, install two
                 RELATIVE relocations.  */
-             if (local_symbol_p)
+             if (!dynamic_symbol_p)
                {
                  unsigned int dyn_r_type;