&& h->root.type != bfd_link_hash_undefweak)
{
h->forced_local = 1;
- return TRUE;
+ if (!elf_hash_table (info)->is_relocatable_executable)
+ return TRUE;
}
default:
bfd_boolean provide)
{
struct elf_link_hash_entry *h;
+ struct elf_link_hash_table *htab;
if (!is_elf_hash_table (info->hash))
return TRUE;
- h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, TRUE, FALSE);
+ htab = elf_hash_table (info);
+ h = elf_link_hash_lookup (htab, name, !provide, TRUE, FALSE);
if (h == NULL)
- return FALSE;
+ return provide;
/* Since we're defining the symbol, don't let it seem to have not
been defined. record_dynamic_symbol and size_dynamic_sections
if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_undefined)
{
- struct elf_link_hash_table *htab = elf_hash_table (info);
-
+ h->root.type = bfd_link_hash_new;
if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root)
bfd_link_repair_undef_list (&htab->root);
- h->root.type = bfd_link_hash_new;
}
if (h->root.type == bfd_link_hash_new)
h->def_regular = 1;
+ /* STV_HIDDEN and STV_INTERNAL symbols must be STB_LOCAL in shared objects
+ and executables. */
+ if (!info->relocatable
+ && h->dynindx != -1
+ && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+ h->forced_local = 1;
+
if ((h->def_dynamic
|| h->ref_dynamic
- || info->shared)
+ || info->shared
+ || (info->executable && elf_hash_table (info)->is_relocatable_executable))
&& h->dynindx == -1)
{
if (! bfd_elf_link_record_dynamic_symbol (info, h))
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->forced_local)
+ return TRUE;
+
+ if (h->dynindx != -1)
+ h->dynindx = ++(*count);
+
+ return TRUE;
+}
+
+
+/* Like elf_link_renumber_hash_table_dynsyms, but just number symbols with
+ STB_LOCAL binding. */
+
+static bfd_boolean
+elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
+ void *data)
+{
+ size_t *count = data;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if (!h->forced_local)
+ return TRUE;
+
if (h->dynindx != -1)
h->dynindx = ++(*count);
}
/* Assign dynsym indices. In a shared library we generate a section
- symbol for each output section, which come first. Next come all of
- the back-end allocated local dynamic syms, followed by the rest of
- the global symbols. */
+ symbol for each output section, which come first. Next come symbols
+ which have been forced to local binding. Then all of the back-end
+ allocated local dynamic syms, followed by the rest of the global
+ symbols. */
unsigned long
_bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
{
unsigned long dynsymcount = 0;
- if (info->shared)
+ if (info->shared || elf_hash_table (info)->is_relocatable_executable)
{
const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
asection *p;
elf_section_data (p)->dynindx = ++dynsymcount;
}
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_link_renumber_local_hash_table_dynsyms,
+ &dynsymcount);
+
if (elf_hash_table (info)->dynlocal)
{
struct elf_link_local_dynamic_entry *p;
return TRUE;
case bfd_link_hash_undefined:
+ if (h->root.u.undef.abfd != inf->not_needed)
+ return TRUE;
+ if (h->root.u.undef.weak != NULL
+ && h->root.u.undef.weak != inf->not_needed)
+ {
+ /* Symbol was undefweak in u.undef.weak bfd, and has become
+ undefined in as-needed lib. Restore weak. */
+ h->root.type = bfd_link_hash_undefweak;
+ h->root.u.undef.abfd = h->root.u.undef.weak;
+ if (h->root.u.undef.next != NULL
+ || inf->htab->root.undefs_tail == &h->root)
+ inf->twiddled = TRUE;
+ return TRUE;
+ }
+ break;
+
case bfd_link_hash_undefweak:
if (h->root.u.undef.abfd != inf->not_needed)
return TRUE;
break;
}
+ /* There is no way we can undo symbol table state from defined or
+ defweak back to undefined. */
+ if (h->ref_regular)
+ abort ();
+
/* Set sym back to newly created state, but keep undefs list pointer. */
bh = h->root.u.undef.next;
if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
{
char *msg;
bfd_size_type sz;
- bfd_size_type prefix_len;
- const char * gnu_warning_prefix = _("warning: ");
name += sizeof ".gnu.warning." - 1;
}
sz = s->size;
- prefix_len = strlen (gnu_warning_prefix);
- msg = bfd_alloc (abfd, prefix_len + sz + 1);
+ msg = bfd_alloc (abfd, sz + 1);
if (msg == NULL)
goto error_return;
- strcpy (msg, gnu_warning_prefix);
- if (! bfd_get_section_contents (abfd, s, msg + prefix_len, 0, sz))
+ if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
goto error_return;
- msg[prefix_len + sz] = '\0';
+ msg[sz] = '\0';
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, BSF_WARNING, s, 0, msg,
{
asection *s;
- if (inputobj->flags & DYNAMIC)
+ if (inputobj->flags & (DYNAMIC | BFD_LINKER_CREATED))
continue;
s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
if (s)
For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
as well as linker_mark. */
if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
- && isec != NULL
- && ((! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
+ && (isec == NULL
+ || (! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
|| (! finfo->info->relocatable
&& (isec->flags & SEC_EXCLUDE) != 0)))
continue;
long last_local = 0;
/* Write out the section symbols for the output sections. */
- if (info->shared)
+ if (info->shared || elf_hash_table (info)->is_relocatable_executable)
{
asection *s;