aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf.c18
-rw-r--r--bfd/elflink.c26
-rw-r--r--bfd/elflink.h21
4 files changed, 65 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 9522755..063dbce 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elf.c b/bfd/elf.c
index c58bd23..f97a9a9 100644
--- 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);
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index c30915b..ce78b59 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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;
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 1cf6be9..f15c693 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -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