/* Intel 80386/80486-specific support for 32-bit ELF
- Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "sysdep.h"
#include "bfdlink.h"
#include "libbfd.h"
-#include "libelf.h"
+#include "elf-bfd.h"
static reloc_howto_type *elf_i386_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
- long r_symndx;
+ unsigned long r_symndx;
struct elf_link_hash_entry *h;
r_symndx = ELF32_R_SYM (rel->r_info);
if (local_got_offsets == NULL)
{
size_t size;
- register int i;
+ register unsigned int i;
size = symtab_hdr->sh_info * sizeof (bfd_vma);
local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
if (local_got_offsets == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
elf_local_got_offsets (abfd) = local_got_offsets;
for (i = 0; i < symtab_hdr->sh_info; i++)
local_got_offsets[i] = (bfd_vma) -1;
case R_386_32:
case R_386_PC32:
if (info->shared
- && (sec->flags & SEC_ALLOC) != 0)
+ && (sec->flags & SEC_ALLOC) != 0
+ && (ELF32_R_TYPE (rel->r_info) != R_386_PC32 || h != NULL))
{
/* When creating a shared object, we must copy these
reloc types into the output file. We create a reloc
/* Make sure we know what is going on here. */
BFD_ASSERT (dynobj != NULL
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+ || h->weakdef != NULL
|| ((h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->elf_link_hash_flags
/* Remember whether there are any reloc sections other
than .rel.plt. */
if (strcmp (name, ".rel.plt") != 0)
- relocs = true;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL entry. */
- target = bfd_get_section_by_name (output_bfd, name + 4);
- if (target != NULL
- && (target->flags & SEC_READONLY) != 0)
- reltext = true;
+ {
+ relocs = true;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL
+ entry. The entries in the .rel.plt section
+ really apply to the .got section, which we
+ created ourselves and so know is not readonly. */
+ target = bfd_get_section_by_name (output_bfd, name + 4);
+ if (target != NULL
+ && (target->flags & SEC_READONLY) != 0)
+ reltext = true;
+ }
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
/* Allocate memory for the section contents. */
s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
}
if (elf_hash_table (info)->dynamic_sections_created)
{
int r_type;
reloc_howto_type *howto;
- long r_symndx;
+ unsigned long r_symndx;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
else
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
|| (r_type == R_386_PLT32
&& h->plt_offset != (bfd_vma) -1)
|| (r_type == R_386_GOT32
- && elf_hash_table (info)->dynamic_sections_created)
+ && elf_hash_table (info)->dynamic_sections_created
+ && (! info->shared
+ || ! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
|| (info->shared
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)
&& (r_type == R_386_32
|| r_type == R_386_PC32)
&& (input_section->flags & SEC_ALLOC) != 0))
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared)
+ else if (info->shared && !info->symbolic)
relocation = 0;
else
{
off = h->got_offset;
BFD_ASSERT (off != (bfd_vma) -1);
- if (! elf_hash_table (info)->dynamic_sections_created)
+ if (! elf_hash_table (info)->dynamic_sections_created
+ || (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
- /* This is actually a static link. We must
- initialize this entry in the global offset table.
- Since the offset must always be a multiple of 4,
- we use the least significant bit to record
- whether we have initialized it already.
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally. We must initialize this entry in the
+ global offset table. Since the offset must
+ always be a multiple of 4, we use the least
+ significant bit to record whether we have
+ initialized it already.
When doing a dynamic link, we create a .rel.got
relocation entry to initialize the value. This
if (h->plt_offset == (bfd_vma) -1)
{
/* We didn't make a PLT entry for this symbol. This
- happens when statically linking PIC code. */
+ happens when statically linking PIC code, or when
+ using -Bsymbolic. */
break;
}
case R_386_PC32:
if (info->shared
&& (input_section->flags & SEC_ALLOC) != 0
- && (r_type != R_386_PC32 || h != NULL))
+ && (r_type != R_386_PC32
+ || (h != NULL
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))))
{
Elf_Internal_Rel outrel;
+ boolean relocate;
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
if (r_type == R_386_PC32)
{
BFD_ASSERT (h != NULL && h->dynindx != -1);
+ relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
}
else
{
- if (h == NULL)
- outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ if (h == NULL
+ || (info->symbolic
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) != 0))
+ {
+ relocate = true;
+ outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ }
else
{
- BFD_ASSERT (h->dynindx != (bfd_vma) -1);
+ BFD_ASSERT (h->dynindx != -1);
+ relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32);
}
}
not want to fiddle with the addend. Otherwise, we
need to include the symbol value so that it becomes
an addend for the dynamic reloc. */
- if (h != NULL)
+ if (! relocate)
continue;
}
srel = bfd_get_section_by_name (dynobj, ".rel.got");
BFD_ASSERT (sgot != NULL && srel != NULL);
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
-
rel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
- + h->got_offset);
- rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
+ + (h->got_offset &~ 1));
+
+ /* If this is a -Bsymbolic link, and the symbol is defined
+ locally, we just want to emit a RELATIVE reloc. The entry in
+ the global offset table will already have been initialized in
+ the relocate_section function. */
+ if (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+ rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ else
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
+ }
+
bfd_elf32_swap_reloc_out (output_bfd, &rel,
((Elf32_External_Rel *) srel->contents
+ srel->reloc_count));
#define elf_backend_finish_dynamic_sections \
elf_i386_finish_dynamic_sections
#define elf_backend_want_got_plt 1
-#define elf_backend_plt_readonly 0
+#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
#include "elf32-target.h"