aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.h
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2003-03-06 00:56:43 +0000
committerDavid Carlton <carlton@bactrian.org>2003-03-06 00:56:43 +0000
commitea00b6ec6bf5ed83e0c0310feaa6c6559ee7e84a (patch)
tree6f941d2e6c4a8d032dcc1f9d7a3684171bd716c9 /bfd/elflink.h
parent07297283f46fcad05679b32b8109625b0c7d8670 (diff)
downloadgdb-ea00b6ec6bf5ed83e0c0310feaa6c6559ee7e84a.zip
gdb-ea00b6ec6bf5ed83e0c0310feaa6c6559ee7e84a.tar.gz
gdb-ea00b6ec6bf5ed83e0c0310feaa6c6559ee7e84a.tar.bz2
2003-03-05 David Carlton <carlton@math.stanford.edu>
* Merge with mainline. Tag is carlton_dictionary-20030305-merge.
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r--bfd/elflink.h222
1 files changed, 146 insertions, 76 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h
index a70f873..7d2d2e2 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -2,21 +2,21 @@
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* ELF linker code. */
@@ -1168,6 +1168,8 @@ elf_link_add_object_symbols (abfd, info)
Elf_External_Versym *extversym = NULL;
Elf_External_Versym *ever;
struct elf_link_hash_entry *weaks;
+ struct elf_link_hash_entry **nondeflt_vers = NULL;
+ bfd_size_type nondeflt_vers_cnt = 0;
Elf_Internal_Sym *isymbuf = NULL;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
@@ -1997,6 +1999,23 @@ elf_link_add_object_symbols (abfd, info)
override, dt_needed))
goto error_free_vers;
+ if (definition && (abfd->flags & DYNAMIC) == 0)
+ {
+ char *p = strchr (name, ELF_VER_CHR);
+ if (p != NULL && p[1] != ELF_VER_CHR)
+ {
+ /* Queue non-default versions so that .symver x, x@FOO
+ aliases can be checked. */
+ if (! nondeflt_vers)
+ {
+ amt = (isymend - isym + 1)
+ * sizeof (struct elf_link_hash_entry *);
+ nondeflt_vers = bfd_malloc (amt);
+ }
+ nondeflt_vers [nondeflt_vers_cnt++] = h;
+ }
+ }
+
if (dynsym && h->dynindx == -1)
{
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
@@ -2071,6 +2090,55 @@ elf_link_add_object_symbols (abfd, info)
}
}
+ /* Now that all the symbols from this input file are created, handle
+ .symver foo, foo@BAR such that any relocs against foo become foo@BAR. */
+ if (nondeflt_vers != NULL)
+ {
+ bfd_size_type cnt, symidx;
+
+ for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt)
+ {
+ struct elf_link_hash_entry *h = nondeflt_vers[cnt], *hi;
+ char *shortname, *p;
+
+ p = strchr (h->root.root.string, ELF_VER_CHR);
+ if (p == NULL
+ || (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak))
+ continue;
+
+ amt = p - h->root.root.string;
+ shortname = bfd_malloc (amt + 1);
+ memcpy (shortname, h->root.root.string, amt);
+ shortname[amt] = '\0';
+
+ hi = (struct elf_link_hash_entry *)
+ bfd_link_hash_lookup (info->hash, shortname,
+ FALSE, FALSE, FALSE);
+ if (hi != NULL
+ && hi->root.type == h->root.type
+ && hi->root.u.def.value == h->root.u.def.value
+ && hi->root.u.def.section == h->root.u.def.section)
+ {
+ (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+ hi->root.type = bfd_link_hash_indirect;
+ hi->root.u.i.link = (struct bfd_link_hash_entry *) h;
+ (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
+ sym_hash = elf_sym_hashes (abfd);
+ if (sym_hash)
+ for (symidx = 0; symidx < extsymcount; ++symidx)
+ if (sym_hash[symidx] == hi)
+ {
+ sym_hash[symidx] = h;
+ break;
+ }
+ }
+ free (shortname);
+ }
+ free (nondeflt_vers);
+ nondeflt_vers = NULL;
+ }
+
if (extversym != NULL)
{
free (extversym);
@@ -2277,6 +2345,8 @@ elf_link_add_object_symbols (abfd, info)
return TRUE;
error_free_vers:
+ if (nondeflt_vers != NULL)
+ free (nondeflt_vers);
if (extversym != NULL)
free (extversym);
error_free_sym:
@@ -2509,7 +2579,10 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
else if (shdr->sh_entsize == sizeof (Elf_External_Rela))
swap_in = bed->s->swap_reloca_in;
else
- abort ();
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
erela = external_relocs;
erelaend = erela + NUM_SHDR_ENTRIES (shdr) * shdr->sh_entsize;
@@ -4878,18 +4951,24 @@ elf_bfd_final_link (abfd, info)
merged = FALSE;
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
o->reloc_count = 0;
for (p = o->link_order_head; p != NULL; p = p->next)
{
+ unsigned int reloc_count = 0;
+ struct bfd_elf_section_data *esdi = NULL;
+ unsigned int *rel_count1;
+
if (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order)
- ++o->reloc_count;
+ reloc_count = 1;
else if (p->type == bfd_indirect_link_order)
{
asection *sec;
sec = p->u.indirect.section;
+ esdi = elf_section_data (sec);
/* Mark all sections which are to be included in the
link. This will normally be every section. We need
@@ -4901,7 +4980,7 @@ elf_bfd_final_link (abfd, info)
merged = TRUE;
if (info->relocateable || info->emitrelocations)
- o->reloc_count += sec->reloc_count;
+ reloc_count = sec->reloc_count;
else if (bed->elf_backend_count_relocs)
{
Elf_Internal_Rela * relocs;
@@ -4910,8 +4989,7 @@ elf_bfd_final_link (abfd, info)
(abfd, sec, (PTR) NULL,
(Elf_Internal_Rela *) NULL, info->keep_memory));
- o->reloc_count
- += (*bed->elf_backend_count_relocs) (sec, relocs);
+ reloc_count = (*bed->elf_backend_count_relocs) (sec, relocs);
if (elf_section_data (o)->relocs != relocs)
free (relocs);
@@ -4954,6 +5032,56 @@ elf_bfd_final_link (abfd, info)
}
}
}
+
+ if (reloc_count == 0)
+ continue;
+
+ o->reloc_count += reloc_count;
+
+ /* MIPS may have a mix of REL and RELA relocs on sections.
+ To support this curious ABI we keep reloc counts in
+ elf_section_data too. We must be careful to add the
+ relocations from the input section to the right output
+ count. FIXME: Get rid of one count. We have
+ o->reloc_count == esdo->rel_count + esdo->rel_count2. */
+ rel_count1 = &esdo->rel_count;
+ if (esdi != NULL)
+ {
+ bfd_boolean same_size;
+ bfd_size_type entsize1;
+
+ entsize1 = esdi->rel_hdr.sh_entsize;
+ BFD_ASSERT (entsize1 == sizeof (Elf_External_Rel)
+ || entsize1 == sizeof (Elf_External_Rela));
+ same_size = (!o->use_rela_p
+ == (entsize1 == sizeof (Elf_External_Rel)));
+
+ if (!same_size)
+ rel_count1 = &esdo->rel_count2;
+
+ if (esdi->rel_hdr2 != NULL)
+ {
+ bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize;
+ unsigned int alt_count;
+ unsigned int *rel_count2;
+
+ BFD_ASSERT (entsize2 != entsize1
+ && (entsize2 == sizeof (Elf_External_Rel)
+ || entsize2 == sizeof (Elf_External_Rela)));
+
+ rel_count2 = &esdo->rel_count2;
+ if (!same_size)
+ rel_count2 = &esdo->rel_count;
+
+ /* The following is probably too simplistic if the
+ backend counts output relocs unusually. */
+ BFD_ASSERT (bed->elf_backend_count_relocs == NULL);
+ alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2);
+ *rel_count2 += alt_count;
+ reloc_count -= alt_count;
+ }
+ }
+ *rel_count1 += reloc_count;
}
if (o->reloc_count > 0)
@@ -4987,63 +5115,6 @@ elf_bfd_final_link (abfd, info)
if (! _bfd_elf_compute_section_file_positions (abfd, info))
goto error_return;
- /* Figure out how many relocations we will have in each section.
- Just using RELOC_COUNT isn't good enough since that doesn't
- maintain a separate value for REL vs. RELA relocations. */
- if (emit_relocs)
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
- for (o = sub->sections; o != NULL; o = o->next)
- {
- asection *output_section;
-
- if (! o->linker_mark)
- {
- /* This section was omitted from the link. */
- continue;
- }
-
- output_section = o->output_section;
-
- if (output_section != NULL
- && (o->flags & SEC_RELOC) != 0)
- {
- struct bfd_elf_section_data *esdi
- = elf_section_data (o);
- struct bfd_elf_section_data *esdo
- = elf_section_data (output_section);
- unsigned int *rel_count;
- unsigned int *rel_count2;
- bfd_size_type entsize;
- bfd_size_type entsize2;
-
- /* We must be careful to add the relocations from the
- input section to the right output count. */
- entsize = esdi->rel_hdr.sh_entsize;
- entsize2 = esdi->rel_hdr2 ? esdi->rel_hdr2->sh_entsize : 0;
- BFD_ASSERT ((entsize == sizeof (Elf_External_Rel)
- || entsize == sizeof (Elf_External_Rela))
- && entsize2 != entsize
- && (entsize2 == 0
- || entsize2 == sizeof (Elf_External_Rel)
- || entsize2 == sizeof (Elf_External_Rela)));
- if (entsize == esdo->rel_hdr.sh_entsize)
- {
- rel_count = &esdo->rel_count;
- rel_count2 = &esdo->rel_count2;
- }
- else
- {
- rel_count = &esdo->rel_count2;
- rel_count2 = &esdo->rel_count;
- }
-
- *rel_count += NUM_SHDR_ENTRIES (& esdi->rel_hdr);
- if (esdi->rel_hdr2)
- *rel_count2 += NUM_SHDR_ENTRIES (esdi->rel_hdr2);
- output_section->flags |= SEC_RELOC;
- }
- }
-
/* That created the reloc sections. Set their sizes, and assign
them file positions, and allocate some buffers. */
for (o = abfd->sections; o != NULL; o = o->next)
@@ -6096,8 +6167,7 @@ elf_link_output_extsym (h, data)
referenced by regular files, because we will already have issued
warnings for them. */
if (! finfo->info->relocateable
- && ! finfo->info->allow_shlib_undefined
- && ! finfo->info->shared
+ && (! finfo->info->shared || ! finfo->info->allow_shlib_undefined)
&& h->root.type == bfd_link_hash_undefined
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0