ELF visibility patch from Martin Loewis.
authorNick Clifton <nickc@redhat.com>
Mon, 3 Jan 2000 18:32:21 +0000 (18:32 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 3 Jan 2000 18:32:21 +0000 (18:32 +0000)
bfd/ChangeLog
bfd/elf.c
bfd/elflink.c
bfd/elflink.h

index 9522755bd4c994e64a9e471fbbc5fa28592ab934..063dbce4b9dc877d287a3e14314eee07ce4ff2b7 100644 (file)
@@ -1,3 +1,10 @@
+2000-01-03  Martin v. Loewis  <loewis@informatik.hu-berlin.de>
+
+       * elflink.c (_bfd_elf_link_record_dynamic_symbol): Process symbol
+       visibility.
+       * elflink.h (elf_link_add_object_symbols): Combine visibilities.
+       * elf.c (bfd_elf_print_symbol): Interpret st_other as visibility.
+
 1999-12-29  Richard Henderson  <rth@cygnus.com>
 
        * elflink.h (bfd_elf,size_dynamic_sections): Don't export all
index c58bd2329d0e6ccd1ba9fb403f14b11ed675f5d6..f97a9a98cc8ef9204b1b7685c0209f5c1faaa53c 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -761,6 +761,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
        CONST char *section_name;
        CONST char *name = NULL;
        struct elf_backend_data *bed;
+       unsigned char st_other;
        
        section_name = symbol->section ? symbol->section->name : "(*none*)";
 
@@ -836,10 +837,19 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
          }
 
        /* If the st_other field is not zero, print it.  */
-       if (((elf_symbol_type *) symbol)->internal_elf_sym.st_other != 0)
-         fprintf (file, " 0x%02x",
-                  ((unsigned int)
-                   ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
+       st_other = ((elf_symbol_type *) symbol)->internal_elf_sym.st_other;
+       
+       switch (st_other)
+         {
+         case 0: break;
+         case STV_INTERNAL:  fprintf (file, " .internal");  break;
+         case STV_HIDDEN:    fprintf (file, " .hidden");    break;
+         case STV_PROTECTED: fprintf (file, " .protected"); break;
+         default:
+           /* Some other non-defined flags are also present, so print
+              everything hex.  */
+           fprintf (file, " 0x%02x", (unsigned int) st_other);
+         }
 
        fprintf (file, " %s", name);
       }
index c30915be5db36a97f83d024e6c8906fb244eafbf..ce78b59400dccb4c3eb679dfa52ac4481c923cde 100644 (file)
@@ -218,6 +218,32 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
       boolean copy;
       bfd_size_type indx;
 
+      /* XXX: The ABI draft says the linker must turn hidden and
+        internal symbols into STB_LOCAL symbols when producing the
+        DSO. However, if ld.so honors st_other in the dynamic table,
+        this would not be necessary.  */
+      switch (ELF_ST_VISIBILITY (h->other))
+       {
+       case STV_INTERNAL:
+       case STV_HIDDEN:
+         /* This symbol must be defined in the shared object or
+            executable.  */
+         if (h->root.type == bfd_link_hash_undefined)
+           {
+             bfd * abfd = h->root.u.undef.abfd;
+             char * name = h->root.root.string;
+             
+             (*info->callbacks->undefined_symbol)
+               (info, name, abfd, bfd_und_section_ptr, 0);
+           }
+         
+         h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+         break;
+         
+       default:
+         break;
+       }
+
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;
 
index 1cf6be991e20d462f3c71052ef67513ed59355d9..f15c693422c3fe84f7339a4cdcdeb4bdaa3aac70 100644 (file)
@@ -1566,9 +1566,24 @@ elf_link_add_object_symbols (abfd, info)
              h->type = ELF_ST_TYPE (sym.st_info);
            }
 
-         if (sym.st_other != 0
-             && (definition || h->other == 0))
-           h->other = sym.st_other;
+         /* If st_other has a processor-specific meaning, specific code
+            might be needed here.  */
+         if (sym.st_other != 0)
+           {
+             /* Combine visibilities, using the most constraining one.  */
+             unsigned char hvis   = ELF_ST_VISIBILITY (h->other);
+             unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other);
+             
+             if (symvis && (hvis > symvis || hvis == 0))
+               h->other = sym.st_other;
+             
+             /* If neither has visibility, use the st_other of the
+                definition.  This is an arbitrary choice, since the
+                other bits have no general meaning.  */
+             if (!symvis && !hvis
+                 && (definition || h->other == 0))
+               h->other = sym.st_other;
+           }
 
          /* Set a flag in the hash table entry indicating the type of
             reference or definition we just found.  Keep a count of