&& h->root.type != bfd_link_hash_undefweak)
{
h->forced_local = 1;
- return TRUE;
+ if (!elf_hash_table (info)->is_relocatable_executable)
+ return TRUE;
}
default:
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;
TYPE_CHANGE_OK if it is OK for the type to change. We set
SIZE_CHANGE_OK if it is OK for the size to change. By OK to
change, we mean that we shouldn't warn if the type or size does
- change. */
+ change. We set POLD_ALIGNMENT if an old common symbol in a dynamic
+ object is overridden by a regular object. */
bfd_boolean
_bfd_elf_merge_symbol (bfd *abfd,
Elf_Internal_Sym *sym,
asection **psec,
bfd_vma *pvalue,
+ unsigned int *pold_alignment,
struct elf_link_hash_entry **sym_hash,
bfd_boolean *skip,
bfd_boolean *override,
if (h->size > *pvalue)
*pvalue = h->size;
- /* FIXME: We no longer know the alignment required by the symbol
- in the dynamic object, so we just wind up using the one from
- the regular object. */
+ /* We need to remember the alignment required by the symbol
+ in the dynamic object. */
+ BFD_ASSERT (pold_alignment);
+ *pold_alignment = h->root.u.def.section->alignment_power;
olddef = FALSE;
olddyncommon = FALSE;
size_change_ok = FALSE;
sec = *psec;
if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
- &hi, &skip, &override, &type_change_ok,
- &size_change_ok))
+ NULL, &hi, &skip, &override,
+ &type_change_ok, &size_change_ok))
return FALSE;
if (skip)
size_change_ok = FALSE;
sec = *psec;
if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
- &hi, &skip, &override, &type_change_ok,
- &size_change_ok))
+ NULL, &hi, &skip, &override,
+ &type_change_ok, &size_change_ok))
return FALSE;
if (skip)
{
int bind;
bfd_vma value;
- asection *sec;
+ asection *sec, *new_sec;
flagword flags;
const char *name;
struct elf_link_hash_entry *h;
sec = bfd_abs_section_ptr;
else if (sec->kept_section)
{
- /* Symbols from discarded section are undefined. */
+ /* Symbols from discarded section are undefined, and have
+ default visibility. */
sec = bfd_und_section_ptr;
isym->st_shndx = SHN_UNDEF;
+ isym->st_other = STV_DEFAULT
+ | (isym->st_other & ~ ELF_ST_VISIBILITY(-1));
}
else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
value -= sec->vma;
type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
old_alignment = 0;
old_bfd = NULL;
+ new_sec = sec;
if (is_elf_hash_table (hash_table))
{
name = newname;
}
- if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
+ if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
+ &value, &old_alignment,
sym_hash, &skip, &override,
&type_change_ok, &size_change_ok))
goto error_free_vers;
}
/* Set the alignment of a common symbol. */
- if (isym->st_shndx == SHN_COMMON
+ if ((isym->st_shndx == SHN_COMMON
+ || bfd_is_com_section (sec))
&& h->root.type == bfd_link_hash_common)
{
unsigned int align;
- align = bfd_log2 (isym->st_value);
+ if (isym->st_shndx == SHN_COMMON)
+ align = bfd_log2 (isym->st_value);
+ else
+ {
+ /* The new symbol is a common symbol in a shared object.
+ We need to get the alignment from the section. */
+ align = new_sec->alignment_power;
+ }
if (align > old_alignment
/* Permit an alignment power of zero if an alignment of one
is specified and no other alignments have been specified. */
{
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;