}
s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
+ (bed->rela_plts_and_copies_p
? ".rela.plt" : ".rel.plt"),
flags | SEC_READONLY);
if (s == NULL
if (! info->shared)
{
s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
+ (bed->rela_plts_and_copies_p
? ".rela.bss" : ".rel.bss"),
flags | SEC_READONLY);
if (s == NULL
int bind;
bfd *oldbfd;
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
- bfd_boolean newweak, oldweak;
+ bfd_boolean newweak, oldweak, newfunc, oldfunc;
const struct elf_backend_data *bed;
*skip = FALSE;
return FALSE;
*sym_hash = h;
+ bed = get_elf_backend_data (abfd);
+
/* This code is for coping with dynamic objects, and is only useful
if we are doing an ELF link. */
- if (info->output_bfd->xvec != abfd->xvec)
+ if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
return TRUE;
/* For merging, we only care about real symbols. */
&& h->root.type != bfd_link_hash_undefweak
&& h->root.type != bfd_link_hash_common);
- bed = get_elf_backend_data (abfd);
+ /* NEWFUNC and OLDFUNC indicate whether the new or old symbol,
+ respectively, appear to be a function. */
+
+ newfunc = (ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+ && bed->is_function_type (ELF_ST_TYPE (sym->st_info)));
+
+ oldfunc = (h->type != STT_NOTYPE
+ && bed->is_function_type (h->type));
+
/* When we try to create a default indirect symbol from the dynamic
definition with the default version, we skip it if its type and
the type of existing regular definition mismatch. We only do it
&& ELF_ST_TYPE (sym->st_info) != h->type
&& ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
&& h->type != STT_NOTYPE
- && !(bed->is_function_type (ELF_ST_TYPE (sym->st_info))
- && bed->is_function_type (h->type)))
+ && !(newfunc && oldfunc))
{
*skip = TRUE;
return TRUE;
oldweak = FALSE;
/* Allow changes between different types of funciton symbol. */
- if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))
- && bed->is_function_type (h->type))
+ if (newfunc && oldfunc)
*type_change_ok = TRUE;
/* It's OK to change the type if either the existing symbol or the
&& (sec->flags & SEC_ALLOC) != 0
&& (sec->flags & SEC_LOAD) == 0
&& sym->st_size > 0
- && !bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
+ && !newfunc)
newdyncommon = TRUE;
else
newdyncommon = FALSE;
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& (h->root.u.def.section->flags & SEC_LOAD) == 0
&& h->size > 0
- && !bed->is_function_type (h->type))
+ && !oldfunc)
olddyncommon = TRUE;
else
olddyncommon = FALSE;
&& newdef
&& (olddef
|| (h->root.type == bfd_link_hash_common
- && (newweak
- || bed->is_function_type (ELF_ST_TYPE (sym->st_info))))))
+ && (newweak || newfunc))))
{
*override = TRUE;
newdef = FALSE;
if (!newdyn
&& (newdef
|| (bfd_is_com_section (sec)
- && (oldweak
- || bed->is_function_type (h->type))))
+ && (oldweak || oldfunc)))
&& olddyn
&& olddef
&& h->def_dynamic)
overriding a function. */
if (bfd_is_com_section (sec))
- *type_change_ok = TRUE;
+ {
+ if (oldfunc)
+ {
+ /* If a common symbol overrides a function, make sure
+ that it isn't defined dynamically nor has type
+ function. */
+ h->def_dynamic = 0;
+ h->type = STT_NOTYPE;
+ }
+ *type_change_ok = TRUE;
+ }
if ((*sym_hash)->root.type == bfd_link_hash_indirect)
flip = *sym_hash;
size = o->reloc_count;
size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
if (keep_memory)
- internal_relocs = bfd_alloc (abfd, size);
+ internal_relocs = alloc2 = bfd_alloc (abfd, size);
else
internal_relocs = alloc2 = bfd_malloc (size);
if (internal_relocs == NULL)
if (alloc1 != NULL)
free (alloc1);
if (alloc2 != NULL)
- free (alloc2);
+ {
+ if (keep_memory)
+ bfd_release (abfd, alloc2);
+ else
+ free (alloc2);
+ }
return NULL;
}
dynsym = TRUE;
}
- if (definition && (sec->flags & SEC_DEBUGGING))
+ if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
{
/* We don't want to make debug symbol dynamic. */
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
if (hlook->dynindx != -1 && h->dynindx == -1)
{
if (! bfd_elf_link_record_dynamic_symbol (info, h))
- goto error_return;
+ {
+ err_free_sym_hash:
+ free (sorted_sym_hash);
+ goto error_return;
+ }
}
/* If the real definition is in the list of dynamic
if (h->dynindx != -1 && hlook->dynindx == -1)
{
if (! bfd_elf_link_record_dynamic_symbol (info, hlook))
- goto error_return;
+ goto err_free_sym_hash;
}
break;
}
elf_link_hash_traverse (elf_hash_table (info),
elf_collect_hash_codes, &hashinf);
if (hashinf.error)
- return FALSE;
+ {
+ free (hashcodes);
+ return FALSE;
+ }
nsyms = hashinf.hashcodes - hashcodes;
bucketcount
elf_link_hash_traverse (elf_hash_table (info),
elf_collect_gnu_hash_codes, &cinfo);
if (cinfo.error)
- return FALSE;
+ {
+ free (cinfo.hashcodes);
+ return FALSE;
+ }
bucketcount
= compute_bucket_count (info, cinfo.hashcodes, cinfo.nsyms, 1);
sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
}
+ /* If this is a symbol defined in a dynamic library, don't use the
+ symbol size from the dynamic library. Relinking an executable
+ against a new library may introduce gratuitous changes in the
+ executable's symbols if we keep the size. */
+ if (sym.st_shndx == SHN_UNDEF
+ && !h->def_regular
+ && h->def_dynamic)
+ sym.st_size = 0;
+
/* If a non-weak symbol with non-default visibility is not defined
locally, it is a fatal error. */
if (! finfo->info->relocatable
offset += sections[n]->size;
}
+ free (sections);
return TRUE;
}
return ret;
}
+/* For a SHT_GROUP section, return the group signature. For other
+ sections, return the normal section name. */
+
+static const char *
+section_signature (asection *sec)
+{
+ if ((sec->flags & SEC_GROUP) != 0
+ && elf_next_in_group (sec) != NULL
+ && elf_group_name (elf_next_in_group (sec)) != NULL)
+ return elf_group_name (elf_next_in_group (sec));
+ return sec->name;
+}
+
void
-_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
+_bfd_elf_section_already_linked (bfd *abfd, asection *sec,
struct bfd_link_info *info)
{
flagword flags;
causes trouble for MIPS ELF, which relies on link once semantics
to handle the .reginfo section correctly. */
- name = bfd_get_section_name (abfd, sec);
+ name = section_signature (sec);
if (CONST_STRNEQ (name, ".gnu.linkonce.")
&& (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
/* We may have 2 different types of sections on the list: group
sections and linkonce sections. Match like sections. */
if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
- && strcmp (name, l->sec->name) == 0
+ && strcmp (name, section_signature (l->sec)) == 0
&& bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
{
/* The section has already been linked. See if we should