+/* ELF linker support.
+ Copyright 1995 Free Software Foundation, Inc.
+
+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 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. */
+
/* ELF linker code. */
static boolean elf_link_add_object_symbols
bfd *abfd;
struct bfd_link_info *info;
{
- bfd *first;
-
switch (bfd_get_format (abfd))
{
case bfd_object:
return elf_link_add_object_symbols (abfd, info);
case bfd_archive:
- first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
- if (first == NULL)
- {
- /* It's OK to have an empty archive. */
- return true;
- }
- if (! bfd_check_format (first, bfd_object))
- return false;
- if (bfd_get_flavour (first) != bfd_target_elf_flavour)
- {
- /* On Linux, we may have an a.out archive which got
- recognized as an ELF archive. Therefore, we treat all
- archives as though they were actually of the flavour of
- their first element. */
- return (*first->xvec->_bfd_link_add_symbols) (abfd, info);
- }
return elf_link_add_archive_symbols (abfd, info);
default:
bfd_set_error (bfd_error_wrong_format);
continue;
if (h->root.type != bfd_link_hash_undefined)
{
- defined[i] = true;
+ if (h->root.type != bfd_link_hash_undefweak)
+ defined[i] = true;
continue;
}
int elfsec;
unsigned long link;
- dynbuf = (Elf_External_Dyn *) malloc (s->_raw_size);
+ dynbuf = (Elf_External_Dyn *) malloc ((size_t) s->_raw_size);
if (dynbuf == NULL)
{
bfd_set_error (bfd_error_no_memory);
struct bfd_elf_link_needed_list *n, **pn;
char *fnm, *anm;
- n = bfd_alloc (abfd,
- sizeof (struct bfd_elf_link_needed_list));
+ n = (struct bfd_elf_link_needed_list *)
+ bfd_alloc (abfd,
+ sizeof (struct bfd_elf_link_needed_list));
fnm = bfd_elf_string_from_elf_section (abfd, link,
dyn.d_un.d_val);
if (n == NULL || fnm == NULL)
const char *name;
struct elf_link_hash_entry *h = NULL;
boolean definition;
+ boolean new_weakdef;
elf_swap_symbol_in (abfd, esym, &sym);
false, collect, (struct bfd_link_hash_entry **) sym_hash)))
goto error_return;
+ new_weakdef = false;
if (dynamic
&& definition
&& (flags & BSF_WEAK) != 0
(*sym_hash)->weakdef = weaks;
weaks = *sym_hash;
+ new_weakdef = true;
}
/* Get the alignment of a common symbol. */
new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
if ((old_flags & new_flag) != 0
|| (old_flags & (ELF_LINK_HASH_DEF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR)) != 0)
+ | ELF_LINK_HASH_REF_REGULAR)) != 0
+ || (h->weakdef != NULL
+ && (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_REF_DYNAMIC)) != 0))
dynsym = true;
}
{
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
goto error_return;
+ if (h->weakdef != NULL
+ && ! new_weakdef
+ && h->weakdef->dynindx == -1)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (info,
+ h->weakdef))
+ goto error_return;
+ }
}
}
}
if (external_relocs == NULL)
{
- alloc1 = (PTR) malloc (rel_hdr->sh_size);
+ alloc1 = (PTR) malloc ((size_t) rel_hdr->sh_size);
if (alloc1 == NULL)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
+ if (info->symbolic)
+ {
+ if (! elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
+ return false;
+ }
+
if (rpath != NULL)
{
bfd_size_type indx;
isym.st_other = 0;
isym.st_shndx = 0;
elf_swap_symbol_out (output_bfd, &isym,
- (char *) (Elf_External_Sym *) s->contents);
+ (PTR) (Elf_External_Sym *) s->contents);
for (i = 0; elf_buckets[i] != 0; i++)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
- memset (s->contents, 0, s->_raw_size);
+ memset (s->contents, 0, (size_t) s->_raw_size);
put_word (output_bfd, bucketcount, s->contents);
put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
bfd *dynobj;
struct elf_backend_data *bed;
+ /* 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. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+ && eif->info->shared
+ && eif->info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+ h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
+
/* If this symbol does not require a PLT entry, and it is not
defined by a dynamic object, or is not referenced by a regular
- object, ignore it. FIXME: Do we need to worry about symbols
- which are defined by one dynamic object and referenced by another
- one? */
+ object, ignore it. We do have to handle a weak defined symbol,
+ even if no regular object refers to it, if we decided to add it
+ to the dynamic symbol table. FIXME: Do we normally need to worry
+ about symbols which are defined by one dynamic object and
+ referenced by another one? */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
|| (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0))
+ || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+ && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
return true;
/* If we've already adjusted this symbol, don't do it again. This
}
elf_swap_symbol_out (finfo->output_bfd, elfsym,
- (char *) (finfo->symbuf + finfo->symbuf_count));
+ (PTR) (finfo->symbuf + finfo->symbuf_count));
++finfo->symbuf_count;
++finfo->output_bfd->symcount;
}
elf_swap_symbol_out (finfo->output_bfd, &sym,
- (char *) ((Elf_External_Sym *) finfo->dynsym_sec->contents
- + h->dynindx));
+ (PTR) (((Elf_External_Sym *)
+ finfo->dynsym_sec->contents)
+ + h->dynindx));
bucketcount = elf_hash_table (finfo->info)->bucketcount;
bucket = (bfd_elf_hash ((const unsigned char *) h->root.root.string)