diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf.c | 18 | ||||
-rw-r--r-- | bfd/elflink.c | 26 | ||||
-rw-r--r-- | bfd/elflink.h | 21 |
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 @@ -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 |