/* ELF linker support.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
Elf_External_Sym *buf = NULL;
struct elf_link_hash_entry **sym_hash;
boolean dynamic;
- bfd_byte *dynver = NULL;
Elf_External_Versym *extversym = NULL;
Elf_External_Versym *ever;
Elf_External_Dyn *dynbuf = NULL;
Elf_Internal_Shdr *versymhdr;
versymhdr = &elf_tdata (abfd)->dynversym_hdr;
- extversym = (Elf_External_Versym *) bfd_malloc (hdr->sh_size);
+ extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
if (extversym == NULL)
goto error_return;
if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
/* Save the SONAME, if there is one, because sometimes the
linker emulation code will need to know it. */
if (*name == '\0')
- name = bfd_get_filename (abfd);
+ name = basename (bfd_get_filename (abfd));
elf_dt_name (abfd) = name;
}
}
}
+ if (! info->relocateable && ! dynamic)
+ {
+ asection *s;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_MERGE)
+ && ! _bfd_merge_section (abfd,
+ &elf_hash_table (info)->merge_info,
+ s, &elf_section_data (s)->merge_info))
+ goto error_return;
+ }
+
return true;
error_return:
free (buf);
if (dynbuf != NULL)
free (dynbuf);
- if (dynver != NULL)
- free (dynver);
if (extversym != NULL)
free (extversym);
return false;
Elf_Internal_Rel *irel;
erel = (Elf_External_Rel *) external_relocs;
- erelend = erel + shdr->sh_size / shdr->sh_entsize;
+ erelend = erel + NUM_SHDR_ENTRIES (shdr);
irela = internal_relocs;
irel = bfd_alloc (abfd, (bed->s->int_rels_per_ext_rel
* sizeof (Elf_Internal_Rel)));
BFD_ASSERT (shdr->sh_entsize == sizeof (Elf_External_Rela));
erela = (Elf_External_Rela *) external_relocs;
- erelaend = erela + shdr->sh_size / shdr->sh_entsize;
+ erelaend = erela + NUM_SHDR_ENTRIES (shdr);
irela = internal_relocs;
for (; erela < erelaend; erela++, irela += bed->s->int_rels_per_ext_rel)
{
(abfd,
elf_section_data (o)->rel_hdr2,
((bfd_byte *) external_relocs) + rel_hdr->sh_size,
- internal_relocs + (rel_hdr->sh_size / rel_hdr->sh_entsize
+ internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr)
* bed->s->int_rels_per_ext_rel)))
goto error_return;
}
}
+ eif.info = info;
+ eif.failed = false;
+
/* If we are supposed to export all symbols into the dynamic symbol
table (this is not the normal case), then do so. */
if (export_dynamic)
{
- struct elf_info_failed eif;
-
- eif.failed = false;
- eif.info = info;
elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
(PTR) &eif);
if (eif.failed)
/* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */
- eif.failed = false;
- eif.info = info;
elf_link_hash_traverse (elf_hash_table (info),
elf_adjust_dynamic_symbol,
(PTR) &eif);
const char *name;
bfd_size_type indx;
- name = output_bfd->filename;
+ name = basename (output_bfd->filename);
def.vd_hash = bfd_elf_hash (name);
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
name, true, false);
true, false);
else
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
- t->vn_bfd->filename, true, false);
+ basename (t->vn_bfd->filename),
+ true, false);
if (indx == (bfd_size_type) -1)
return false;
t->vn_file = indx;
/* If -Bsymbolic was used (which means to bind references to global
symbols to the definition within the shared object), and this
symbol was defined in a regular object, then it actually doesn't
- need a PLT entry. Likewise, if the symbol has any kind of
- visibility (internal, hidden, or protected), it doesn't need a
- PLT. */
+ need a PLT entry, and we can accomplish that by forcing it local.
+ Likewise, if the symbol has hidden or internal visibility.
+ FIXME: It might be that we also do not need a PLT for other
+ non-hidden visibilities, but we would have to tell that to the
+ backend specifically; we can't just clear PLT-related data here. */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
&& eif->info->shared
- && (eif->info->symbolic || ELF_ST_VISIBILITY (h->other))
+ && (eif->info->symbolic
+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+ || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
{
- h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
- h->plt.offset = (bfd_vma) -1;
+ struct elf_backend_data *bed;
+ bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
+ if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+ || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+ h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+ (*bed->elf_backend_hide_symbol) (eif->info, h);
}
/* If this is a weak defined symbol in a dynamic object, and we know
PARAMS ((struct elf_final_link_info *));
static boolean elf_link_output_extsym
PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_link_sec_merge_syms
+ PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_link_input_bfd
PARAMS ((struct elf_final_link_info *, bfd *));
static boolean elf_reloc_link_order
Elf_Internal_Shdr *symstrtab_hdr;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_outext_info eoinfo;
+ boolean merged;
if (info->shared)
abfd->flags |= DYNAMIC;
max_external_reloc_size = 0;
max_internal_reloc_count = 0;
max_sym_count = 0;
+ merged = false;
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{
o->reloc_count = 0;
the linker has decided to not include. */
sec->linker_mark = true;
+ if (sec->flags & SEC_MERGE)
+ merged = true;
+
if (info->relocateable || info->emitrelocations)
o->reloc_count += sec->reloc_count;
o->vma = 0;
}
+ if (! info->relocateable && merged)
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_link_sec_merge_syms, (PTR) abfd);
+
/* Figure out the file positions for everything but the symbol table
and the relocs. We set symcount to force assign_section_numbers
to create a symbol table. */
rel_count2 = &esdo->rel_count;
}
- *rel_count += (esdi->rel_hdr.sh_size
- / esdi->rel_hdr.sh_entsize);
+ *rel_count += NUM_SHDR_ENTRIES (& esdi->rel_hdr);
if (esdi->rel_hdr2)
- *rel_count2 += (esdi->rel_hdr2->sh_size
- / esdi->rel_hdr2->sh_entsize);
+ *rel_count2 += NUM_SHDR_ENTRIES (esdi->rel_hdr2);
}
}
return true;
}
+/* Adjust all external symbols pointing into SEC_MERGE sections
+ to reflect the object merging within the sections. */
+
+static boolean
+elf_link_sec_merge_syms (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ asection *sec;
+
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
+ && elf_section_data (sec)->merge_info)
+ {
+ bfd *output_bfd = (bfd *) data;
+
+ h->root.u.def.value =
+ _bfd_merged_section_offset (output_bfd,
+ &h->root.u.def.section,
+ elf_section_data (sec)->merge_info,
+ h->root.u.def.value, (bfd_vma) 0);
+ }
+
+ return true;
+}
+
/* Add an external symbol to the symbol table. This is called from
the hash table traversal routine. When generating a shared object,
we go through the symbol table twice. The first time we output
bed = get_elf_backend_data (output_bfd);
irela = internal_relocs;
- irelaend = irela + input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
+ irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr);
if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
{
Elf_External_Rel *erel;
/* Bump the counter, so that we know where to add the next set of
relocations. */
- *rel_countp += input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
+ *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr);
}
/* Link an input file into the linker output file. This function
name = isec->name;
}
else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
- isec = section_from_elf_index (input_bfd, isym->st_shndx);
+ {
+ isec = section_from_elf_index (input_bfd, isym->st_shndx);
+ if (isec && elf_section_data (isec)->merge_info
+ && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
+ isym->st_value =
+ _bfd_merged_section_offset (output_bfd, &isec,
+ elf_section_data (isec)->merge_info,
+ isym->st_value, (bfd_vma) 0);
+ }
else if (isym->st_shndx == SHN_ABS)
{
isec = bfd_abs_section_ptr;
if ((finfo->info->strip == strip_some
&& (bfd_hash_lookup (finfo->info->keep_hash, name, false, false)
== NULL))
- || (finfo->info->discard == discard_l
+ || (((finfo->info->discard == discard_sec_merge
+ && (isec->flags & SEC_MERGE) && ! finfo->info->relocateable)
+ || finfo->info->discard == discard_l)
&& bfd_is_local_label_name (input_bfd, name)))
continue;
elf_link_output_relocs (output_bfd, o,
input_rel_hdr,
internal_relocs);
- internal_relocs
- += input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
+ internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr);
input_rel_hdr = elf_section_data (o)->rel_hdr2;
if (input_rel_hdr)
elf_link_output_relocs (output_bfd, o,
}
/* Write out the modified section contents. */
- if (elf_section_data (o)->stab_info == NULL)
+ if (elf_section_data (o)->stab_info)
+ {
+ if (! (_bfd_write_section_stabs
+ (output_bfd, &elf_hash_table (finfo->info)->stab_info,
+ o, &elf_section_data (o)->stab_info, contents)))
+ return false;
+ }
+ else if (elf_section_data (o)->merge_info)
+ {
+ if (! (_bfd_write_merged_section
+ (output_bfd, o, elf_section_data (o)->merge_info)))
+ return false;
+ }
+ else
{
if (! (o->flags & SEC_EXCLUDE) &&
! bfd_set_section_contents (output_bfd, o->output_section,
: o->_raw_size)))
return false;
}
- else
- {
- if (! (_bfd_write_section_stabs
- (output_bfd, &elf_hash_table (finfo->info)->stab_info,
- o, &elf_section_data (o)->stab_info, contents)))
- return false;
- }
}
return true;