}
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
}
if (entry->isym.st_shndx != SHN_UNDEF
- && (entry->isym.st_shndx < SHN_LORESERVE
- || entry->isym.st_shndx > SHN_HIRESERVE))
+ && entry->isym.st_shndx < SHN_LORESERVE)
{
asection *s;
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;
}
{
asection *s;
- if (inputobj->flags & (DYNAMIC | BFD_LINKER_CREATED))
+ if (inputobj->flags & (DYNAMIC | EXEC_P | BFD_LINKER_CREATED))
continue;
s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
if (s)
{
asection *s;
+ /* Data first, since setting text_index_section changes
+ _bfd_elf_link_omit_section_dynsym. */
for (s = output_bfd->sections; s != NULL; s = s->next)
- if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
- == (SEC_ALLOC | SEC_READONLY))
+ if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
&& !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
{
- elf_hash_table (info)->text_index_section = s;
+ elf_hash_table (info)->data_index_section = s;
break;
}
for (s = output_bfd->sections; s != NULL; s = s->next)
- if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
+ if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
+ == (SEC_ALLOC | SEC_READONLY))
&& !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
{
- elf_hash_table (info)->data_index_section = s;
+ elf_hash_table (info)->text_index_section = s;
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);
static bfd_boolean
check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
{
- if (sym->st_shndx > SHN_HIRESERVE)
+ if (sym->st_shndx >= (SHN_LORESERVE & 0xffff)
+ && sym->st_shndx < SHN_LORESERVE)
{
/* The gABI doesn't support dynamic symbols in output sections
beyond 64k. */
(*_bfd_error_handler)
(_("%B: Too many sections: %d (>= %d)"),
- abfd, bfd_count_sections (abfd), SHN_LORESERVE);
+ abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
}
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
/* If this symbol is defined in a section which we are
discarding, we don't need to keep it. */
if (isym->st_shndx != SHN_UNDEF
- && (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
- && (isec == NULL
- || bfd_section_removed_from_list (output_bfd,
- isec->output_section)))
+ && isym->st_shndx < SHN_LORESERVE
+ && bfd_section_removed_from_list (output_bfd,
+ isec->output_section))
continue;
/* Get the name of the symbol. */
&& elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
&& (elfsec = _bfd_elf_section_from_bfd_section (sub, s))
&& elfsec < elf_numsections (sub)
- && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER)
+ && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER
+ && elf_elfsections (sub)[elfsec]->sh_link < elf_numsections (sub))
{
seen_linkorder++;
linkorder_sec = s;
offset += sections[n]->size;
}
+ free (sections);
return TRUE;
}
/* sh_link is set in assign_section_numbers. */
/* sh_info is set below. */
/* sh_offset is set just below. */
- symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
+ symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
off = elf_tdata (abfd)->next_file_pos;
off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
finfo.symbuf = bfd_malloc (amt);
if (finfo.symbuf == NULL)
goto error_return;
- if (elf_numsections (abfd) > SHN_LORESERVE)
+ if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
{
/* Wild guess at number of output symbols. realloc'd as needed. */
amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
if (!elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
goto error_return;
}
- if (i == SHN_LORESERVE - 1)
- i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
}
}
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