Merge rev 1.8 (only define "ELF_DYNAMIC_INTERPRETER" if it isn't defined

elsewhere.) into Binutils 2.11[.0].
This commit is contained in:
obrien 2001-05-28 05:52:12 +00:00
parent 7c91b2d479
commit 690ca6b517

View File

@ -1,5 +1,6 @@
/* Intel 80386/80486-specific support for 32-bit ELF
Copyright 1993, 94-98, 1999 Free Software Foundation, Inc.
Copyright 1993, 94, 95, 96, 97, 98, 99, 2000
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -58,35 +59,66 @@ static boolean elf_i386_finish_dynamic_sections
static reloc_howto_type elf_howto_table[]=
{
HOWTO(R_386_NONE, 0,0, 0,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_NONE", true,0x00000000,0x00000000,false),
HOWTO(R_386_32, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_32", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_PC32, 0,2,32,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC32", true,0xffffffff,0xffffffff,true),
HOWTO(R_386_GOT32, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOT32", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_PLT32, 0,2,32,true,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PLT32", true,0xffffffff,0xffffffff,true),
HOWTO(R_386_COPY, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_COPY", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_GLOB_DAT, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GLOB_DAT", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_JUMP_SLOT, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_JUMP_SLOT",true,0xffffffff,0xffffffff,false),
HOWTO(R_386_RELATIVE, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_RELATIVE", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_GOTOFF, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTOFF", true,0xffffffff,0xffffffff,false),
HOWTO(R_386_GOTPC, 0,2,32,true,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTPC", true,0xffffffff,0xffffffff,true),
EMPTY_HOWTO (11),
EMPTY_HOWTO (12),
EMPTY_HOWTO (13),
EMPTY_HOWTO (14),
EMPTY_HOWTO (15),
EMPTY_HOWTO (16),
EMPTY_HOWTO (17),
EMPTY_HOWTO (18),
EMPTY_HOWTO (19),
HOWTO(R_386_NONE, 0, 0, 0, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_NONE",
true, 0x00000000, 0x00000000, false),
HOWTO(R_386_32, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_32",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_PC32, 0, 2, 32, true, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_PC32",
true, 0xffffffff, 0xffffffff, true),
HOWTO(R_386_GOT32, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_GOT32",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_PLT32, 0, 2, 32, true, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_PLT32",
true, 0xffffffff, 0xffffffff, true),
HOWTO(R_386_COPY, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_COPY",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_GLOB_DAT, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_GLOB_DAT",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_JUMP_SLOT, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_JUMP_SLOT",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_RELATIVE, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_RELATIVE",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_GOTOFF, 0, 2, 32, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_GOTOFF",
true, 0xffffffff, 0xffffffff, false),
HOWTO(R_386_GOTPC, 0, 2, 32, true, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_GOTPC",
true, 0xffffffff, 0xffffffff, true),
/* We have a gap in the reloc numbers here.
R_386_standard counts the number up to this point, and
R_386_ext_offset is the value to subtract from a reloc type of
R_386_16 thru R_386_PC8 to form an index into this table. */
#define R_386_standard ((unsigned int) R_386_GOTPC + 1)
#define R_386_ext_offset ((unsigned int) R_386_16 - R_386_standard)
/* The remaining relocs are a GNU extension. */
HOWTO(R_386_16, 0,1,16,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_16", true,0xffff,0xffff,false),
HOWTO(R_386_PC16, 0,1,16,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC16", true,0xffff,0xffff,true),
HOWTO(R_386_8, 0,0,8,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_8", true,0xff,0xff,false),
HOWTO(R_386_PC8, 0,0,8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_386_PC8", true,0xff,0xff,true),
};
HOWTO(R_386_16, 0, 1, 16, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_16",
true, 0xffff, 0xffff, false),
HOWTO(R_386_PC16, 0, 1, 16, true, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_PC16",
true, 0xffff, 0xffff, true),
HOWTO(R_386_8, 0, 0, 8, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_8",
true, 0xff, 0xff, false),
HOWTO(R_386_PC8, 0, 0, 8, true, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_386_PC8",
true, 0xff, 0xff, true),
/* Another gap. */
#define R_386_ext ((unsigned int) R_386_PC8 + 1 - R_386_ext_offset)
#define R_386_vt_offset ((unsigned int) R_386_GNU_VTINHERIT - R_386_ext)
/* GNU extension to record C++ vtable hierarchy. */
static reloc_howto_type elf32_i386_vtinherit_howto =
HOWTO (R_386_GNU_VTINHERIT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -99,10 +131,9 @@ static reloc_howto_type elf32_i386_vtinherit_howto =
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false);
false),
/* GNU extension to record C++ vtable member usage. */
static reloc_howto_type elf32_i386_vtentry_howto =
HOWTO (R_386_GNU_VTENTRY, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -115,7 +146,11 @@ static reloc_howto_type elf32_i386_vtentry_howto =
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false);
false)
#define R_386_vt ((unsigned int) R_386_GNU_VTENTRY + 1 - R_386_vt_offset)
};
#ifdef DEBUG_GEN_RELOC
#define TRACE(str) fprintf (stderr, "i386 bfd reloc lookup %d (%s)\n", code, str)
@ -132,76 +167,78 @@ elf_i386_reloc_type_lookup (abfd, code)
{
case BFD_RELOC_NONE:
TRACE ("BFD_RELOC_NONE");
return &elf_howto_table[ (int)R_386_NONE ];
return &elf_howto_table[(unsigned int) R_386_NONE ];
case BFD_RELOC_32:
TRACE ("BFD_RELOC_32");
return &elf_howto_table[ (int)R_386_32 ];
return &elf_howto_table[(unsigned int) R_386_32 ];
case BFD_RELOC_CTOR:
TRACE ("BFD_RELOC_CTOR");
return &elf_howto_table[ (int)R_386_32 ];
return &elf_howto_table[(unsigned int) R_386_32 ];
case BFD_RELOC_32_PCREL:
TRACE ("BFD_RELOC_PC32");
return &elf_howto_table[ (int)R_386_PC32 ];
return &elf_howto_table[(unsigned int) R_386_PC32 ];
case BFD_RELOC_386_GOT32:
TRACE ("BFD_RELOC_386_GOT32");
return &elf_howto_table[ (int)R_386_GOT32 ];
return &elf_howto_table[(unsigned int) R_386_GOT32 ];
case BFD_RELOC_386_PLT32:
TRACE ("BFD_RELOC_386_PLT32");
return &elf_howto_table[ (int)R_386_PLT32 ];
return &elf_howto_table[(unsigned int) R_386_PLT32 ];
case BFD_RELOC_386_COPY:
TRACE ("BFD_RELOC_386_COPY");
return &elf_howto_table[ (int)R_386_COPY ];
return &elf_howto_table[(unsigned int) R_386_COPY ];
case BFD_RELOC_386_GLOB_DAT:
TRACE ("BFD_RELOC_386_GLOB_DAT");
return &elf_howto_table[ (int)R_386_GLOB_DAT ];
return &elf_howto_table[(unsigned int) R_386_GLOB_DAT ];
case BFD_RELOC_386_JUMP_SLOT:
TRACE ("BFD_RELOC_386_JUMP_SLOT");
return &elf_howto_table[ (int)R_386_JUMP_SLOT ];
return &elf_howto_table[(unsigned int) R_386_JUMP_SLOT ];
case BFD_RELOC_386_RELATIVE:
TRACE ("BFD_RELOC_386_RELATIVE");
return &elf_howto_table[ (int)R_386_RELATIVE ];
return &elf_howto_table[(unsigned int) R_386_RELATIVE ];
case BFD_RELOC_386_GOTOFF:
TRACE ("BFD_RELOC_386_GOTOFF");
return &elf_howto_table[ (int)R_386_GOTOFF ];
return &elf_howto_table[(unsigned int) R_386_GOTOFF ];
case BFD_RELOC_386_GOTPC:
TRACE ("BFD_RELOC_386_GOTPC");
return &elf_howto_table[ (int)R_386_GOTPC ];
return &elf_howto_table[(unsigned int) R_386_GOTPC ];
/* The remaining relocs are a GNU extension. */
case BFD_RELOC_16:
TRACE ("BFD_RELOC_16");
return &elf_howto_table[(int) R_386_16];
return &elf_howto_table[(unsigned int) R_386_16 - R_386_ext_offset];
case BFD_RELOC_16_PCREL:
TRACE ("BFD_RELOC_16_PCREL");
return &elf_howto_table[(int) R_386_PC16];
return &elf_howto_table[(unsigned int) R_386_PC16 - R_386_ext_offset];
case BFD_RELOC_8:
TRACE ("BFD_RELOC_8");
return &elf_howto_table[(int) R_386_8];
return &elf_howto_table[(unsigned int) R_386_8 - R_386_ext_offset];
case BFD_RELOC_8_PCREL:
TRACE ("BFD_RELOC_8_PCREL");
return &elf_howto_table[(int) R_386_PC8];
return &elf_howto_table[(unsigned int) R_386_PC8 - R_386_ext_offset];
case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT");
return &elf32_i386_vtinherit_howto;
return &elf_howto_table[(unsigned int) R_386_GNU_VTINHERIT
- R_386_vt_offset];
case BFD_RELOC_VTABLE_ENTRY:
TRACE ("BFD_RELOC_VTABLE_ENTRY");
return &elf32_i386_vtentry_howto;
return &elf_howto_table[(unsigned int) R_386_GNU_VTENTRY
- R_386_vt_offset];
default:
break;
@ -226,22 +263,20 @@ elf_i386_info_to_howto_rel (abfd, cache_ptr, dst)
arelent *cache_ptr;
Elf32_Internal_Rel *dst;
{
enum elf_i386_reloc_type type;
unsigned int r_type = ELF32_R_TYPE (dst->r_info);
unsigned int indx;
type = (enum elf_i386_reloc_type) ELF32_R_TYPE (dst->r_info);
if (type == R_386_GNU_VTINHERIT)
cache_ptr->howto = &elf32_i386_vtinherit_howto;
else if (type == R_386_GNU_VTENTRY)
cache_ptr->howto = &elf32_i386_vtentry_howto;
else if (type < R_386_max
&& (type < FIRST_INVALID_RELOC || type > LAST_INVALID_RELOC))
cache_ptr->howto = &elf_howto_table[(int) type];
else
if ((indx = r_type) >= R_386_standard
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
>= R_386_ext - R_386_standard)
&& ((indx = r_type - R_386_vt_offset) - R_386_ext
>= R_386_vt - R_386_ext))
{
(*_bfd_error_handler) (_("%s: invalid relocation type %d"),
bfd_get_filename (abfd), (int) type);
cache_ptr->howto = &elf_howto_table[(int) R_386_NONE];
bfd_get_filename (abfd), (int) r_type);
indx = (unsigned int) R_386_NONE;
}
cache_ptr->howto = &elf_howto_table[indx];
}
/* Return whether a symbol name implies a local label. The UnixWare
@ -266,10 +301,12 @@ elf_i386_is_local_label_name (abfd, name)
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#ifndef ELF_DYNAMIC_INTERPRETER
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
#endif
/* The size in bytes of an entry in the procedure linkage table. */
#define PLT_ENTRY_SIZE 16
@ -443,7 +480,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
bfd *dynobj;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
bfd_vma *local_got_offsets;
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
asection *sgot;
@ -456,7 +493,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
dynobj = elf_hash_table (info)->dynobj;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
local_got_offsets = elf_local_got_offsets (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
sgot = NULL;
srelgot = NULL;
@ -526,57 +563,54 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
if (h != NULL)
{
if (h->got.offset != (bfd_vma) -1)
if (h->got.refcount == -1)
{
/* We have already allocated space in the .got. */
break;
}
h->got.offset = sgot->_raw_size;
h->got.refcount = 1;
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
srelgot->_raw_size += sizeof (Elf32_External_Rel);
sgot->_raw_size += 4;
srelgot->_raw_size += sizeof (Elf32_External_Rel);
}
else
h->got.refcount += 1;
}
else
{
/* This is a global offset table entry for a local
symbol. */
if (local_got_offsets == NULL)
/* This is a global offset table entry for a local symbol. */
if (local_got_refcounts == NULL)
{
size_t size;
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)
size = symtab_hdr->sh_info * sizeof (bfd_signed_vma);
local_got_refcounts = ((bfd_signed_vma *)
bfd_alloc (abfd, size));
if (local_got_refcounts == NULL)
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;
elf_local_got_refcounts (abfd) = local_got_refcounts;
memset (local_got_refcounts, -1, size);
}
if (local_got_offsets[r_symndx] != (bfd_vma) -1)
if (local_got_refcounts[r_symndx] == -1)
{
/* We have already allocated space in the .got. */
break;
}
local_got_offsets[r_symndx] = sgot->_raw_size;
local_got_refcounts[r_symndx] = 1;
if (info->shared)
{
/* If we are generating a shared object, we need to
output a R_386_RELATIVE reloc so that the dynamic
linker can adjust this GOT entry. */
srelgot->_raw_size += sizeof (Elf32_External_Rel);
sgot->_raw_size += 4;
if (info->shared)
{
/* If we are generating a shared object, we need to
output a R_386_RELATIVE reloc so that the dynamic
linker can adjust this GOT entry. */
srelgot->_raw_size += sizeof (Elf32_External_Rel);
}
}
else
local_got_refcounts[r_symndx] += 1;
}
sgot->_raw_size += 4;
break;
case R_386_PLT32:
@ -592,8 +626,13 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
if (h == NULL)
continue;
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
if (h->plt.refcount == -1)
{
h->plt.refcount = 1;
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
}
else
h->plt.refcount += 1;
break;
case R_386_32:
@ -602,28 +641,33 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
/* If we are creating a shared library, and this is a reloc
against a global symbol, or a non PC relative reloc
against a local symbol, then we need to copy the reloc
into the shared library. However, if we are linking with
-Bsymbolic, we do not need to copy a reloc against a
global symbol which is defined in an object we are
including in the link (i.e., DEF_REGULAR is set). At
this point we have not seen all the input files, so it is
possible that DEF_REGULAR is not set now but will be set
later (it is never cleared). We account for that
possibility below by storing information in the
pcrel_relocs_copied field of the hash table entry. */
against a global symbol, or a non PC relative reloc
against a local symbol, then we need to copy the reloc
into the shared library. However, if we are linking with
-Bsymbolic, we do not need to copy a reloc against a
global symbol which is defined in an object we are
including in the link (i.e., DEF_REGULAR is set). At
this point we have not seen all the input files, so it is
possible that DEF_REGULAR is not set now but will be set
later (it is never cleared). In case of a weak definition,
DEF_REGULAR may be cleared later by a strong definition in
a shared library. We account for that possibility below by
storing information in the relocs_copied field of the hash
table entry. A similar situation occurs when creating
shared libraries and symbol visibility changes render the
symbol local. */
if (info->shared
&& (sec->flags & SEC_ALLOC) != 0
&& (ELF32_R_TYPE (rel->r_info) != R_386_PC32
|| (h != NULL
&& (! info->symbolic
|| h->root.type == bfd_link_hash_defweak
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0))))
{
/* When creating a shared object, we must copy these
reloc types into the output file. We create a reloc
section in dynobj and make room for this reloc. */
reloc types into the output file. We create a reloc
section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
const char *name;
@ -635,9 +679,20 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
if (name == NULL)
return false;
BFD_ASSERT (strncmp (name, ".rel", 4) == 0
&& strcmp (bfd_get_section_name (abfd, sec),
name + 4) == 0);
if (strncmp (name, ".rel", 4) != 0
|| strcmp (bfd_get_section_name (abfd, sec),
name + 4) != 0)
{
if (abfd->my_archive)
(*_bfd_error_handler) (_("%s(%s): bad relocation section name `%s\'"),
bfd_get_filename (abfd->my_archive),
bfd_get_filename (abfd),
name);
else
(*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"),
bfd_get_filename (abfd),
name);
}
sreloc = bfd_get_section_by_name (dynobj, name);
if (sreloc == NULL)
@ -658,15 +713,13 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
sreloc->_raw_size += sizeof (Elf32_External_Rel);
/* If we are linking with -Bsymbolic, and this is a
global symbol, we count the number of PC relative
relocations we have entered for this symbol, so that
we can discard them again if the symbol is later
defined by a regular object. Note that this function
is only called if we are using an elf_i386 linker
hash table, which means that h is really a pointer to
an elf_i386_link_hash_entry. */
if (h != NULL && info->symbolic
/* If this is a global symbol, we count the number of PC
relative relocations we have entered for this symbol,
so that we can discard them later as necessary. Note
that this function is only called if we are using an
elf_i386 linker hash table, which means that h is
really a pointer to an elf_i386_link_hash_entry. */
if (h != NULL
&& ELF32_R_TYPE (rel->r_info) == R_386_PC32)
{
struct elf_i386_link_hash_entry *eh;
@ -770,14 +823,81 @@ elf_i386_gc_mark_hook (abfd, info, rel, h, sym)
static boolean
elf_i386_gc_sweep_hook (abfd, info, sec, relocs)
bfd *abfd ATTRIBUTE_UNUSED;
bfd *abfd;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
asection *sec ATTRIBUTE_UNUSED;
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
asection *sec;
const Elf_Internal_Rela *relocs;
{
/* ??? It would seem that the existing i386 code does no sort
of reference counting or whatnot on its GOT and PLT entries,
so it is not possible to garbage collect them at this time. */
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
bfd *dynobj;
asection *sgot;
asection *srelgot;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
dynobj = elf_hash_table (info)->dynobj;
if (dynobj == NULL)
return true;
sgot = bfd_get_section_by_name (dynobj, ".got");
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; rel++)
switch (ELF32_R_TYPE (rel->r_info))
{
case R_386_GOT32:
case R_386_GOTOFF:
case R_386_GOTPC:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->got.refcount > 0)
{
h->got.refcount -= 1;
if (h->got.refcount == 0)
{
sgot->_raw_size -= 4;
srelgot->_raw_size -= sizeof (Elf32_External_Rel);
}
}
}
else if (local_got_refcounts != NULL)
{
if (local_got_refcounts[r_symndx] > 0)
{
local_got_refcounts[r_symndx] -= 1;
if (local_got_refcounts[r_symndx] == 0)
{
sgot->_raw_size -= 4;
if (info->shared)
srelgot->_raw_size -= sizeof (Elf32_External_Rel);
}
}
}
break;
case R_386_PLT32:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
}
break;
default:
break;
}
return true;
}
@ -816,16 +936,18 @@ elf_i386_adjust_dynamic_symbol (info, h)
if (h->type == STT_FUNC
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
{
if (! info->shared
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
if ((! info->shared
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
|| (info->shared && h->plt.refcount <= 0))
{
/* This case can occur if we saw a PLT32 reloc in an input
file, but the symbol was never referred to by a dynamic
object. In such a case, we don't actually need to build
a procedure linkage table, and we can just do a PC32
reloc instead. */
BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
file, but the symbol was never referred to by a dynamic
object, or if all references were garbage collected. In
such a case, we don't actually need to build a procedure
linkage table, and we can just do a PC32 reloc instead. */
h->plt.offset = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
return true;
}
@ -863,13 +985,11 @@ elf_i386_adjust_dynamic_symbol (info, h)
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
s = bfd_get_section_by_name (dynobj, ".got.plt");
BFD_ASSERT (s != NULL);
s->_raw_size += 4;
/* We also need to make an entry in the .rel.plt section. */
s = bfd_get_section_by_name (dynobj, ".rel.plt");
BFD_ASSERT (s != NULL);
s->_raw_size += sizeof (Elf32_External_Rel);
@ -999,10 +1119,10 @@ elf_i386_size_dynamic_sections (output_bfd, info)
PC relative relocs against symbols defined in a regular object.
We allocated space for them in the check_relocs routine, but we
will not fill them in in the relocate_section routine. */
if (info->shared && info->symbolic)
if (info->shared)
elf_i386_link_hash_traverse (elf_i386_hash_table (info),
elf_i386_discard_copies,
(PTR) NULL);
(PTR) info);
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
@ -1096,8 +1216,12 @@ elf_i386_size_dynamic_sections (output_bfd, info)
continue;
}
/* Allocate memory for the section contents. */
s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
/* Allocate memory for the section contents. We use bfd_zalloc
here in case unused entries are not reclaimed before the
section's contents are written out. This should not happen,
but this way if it does, we get a R_386_NONE reloc instead
of garbage. */
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
return false;
}
@ -1137,6 +1261,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
{
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
info->flags |= DF_TEXTREL;
}
}
@ -1144,26 +1269,32 @@ elf_i386_size_dynamic_sections (output_bfd, info)
}
/* This function is called via elf_i386_link_hash_traverse if we are
creating a shared object with -Bsymbolic. It discards the space
allocated to copy PC relative relocs against symbols which are
defined in regular objects. We allocated space for them in the
creating a shared object. In the -Bsymbolic case, it discards the
space allocated to copy PC relative relocs against symbols which
are defined in regular objects. For the normal non-symbolic case,
we also discard space for relocs that have become local due to
symbol visibility changes. We allocated space for them in the
check_relocs routine, but we won't fill them in in the
relocate_section routine. */
/*ARGSUSED*/
static boolean
elf_i386_discard_copies (h, ignore)
elf_i386_discard_copies (h, inf)
struct elf_i386_link_hash_entry *h;
PTR ignore ATTRIBUTE_UNUSED;
PTR inf;
{
struct elf_i386_pcrel_relocs_copied *s;
struct bfd_link_info *info = (struct bfd_link_info *) inf;
/* We only discard relocs for symbols defined in a regular object. */
if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
return true;
for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
/* If a symbol has been forced local or we have found a regular
definition for the symbolic link case, then we won't be needing
any relocs. */
if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
&& ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
|| info->symbolic))
{
for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
}
return true;
}
@ -1197,9 +1328,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
sym_hashes = elf_sym_hashes (input_bfd);
local_got_offsets = elf_local_got_offsets (input_bfd);
sgot = NULL;
splt = NULL;
sreloc = NULL;
splt = NULL;
sgot = NULL;
if (dynobj != NULL)
{
splt = bfd_get_section_by_name (dynobj, ".plt");
sgot = bfd_get_section_by_name (dynobj, ".got");
}
rel = relocs;
relend = relocs + input_section->reloc_count;
@ -1213,20 +1349,21 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
asection *sec;
bfd_vma relocation;
bfd_reloc_status_type r;
unsigned int indx;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == R_386_GNU_VTINHERIT
|| r_type == R_386_GNU_VTENTRY)
if (r_type == (int) R_386_GNU_VTINHERIT
|| r_type == (int) R_386_GNU_VTENTRY)
continue;
if (r_type < 0
|| r_type >= (int) R_386_max
|| (r_type >= (int) FIRST_INVALID_RELOC
&& r_type <= (int) LAST_INVALID_RELOC))
if ((indx = (unsigned) r_type) >= R_386_standard
&& ((indx = (unsigned) r_type - R_386_ext_offset) - R_386_standard
>= R_386_ext - R_386_standard))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
howto = elf_howto_table + r_type;
howto = elf_howto_table + indx;
r_symndx = ELF32_R_SYM (rel->r_info);
@ -1277,6 +1414,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
sec = h->root.u.def.section;
if (r_type == R_386_GOTPC
|| (r_type == R_386_PLT32
&& splt != NULL
&& h->plt.offset != (bfd_vma) -1)
|| (r_type == R_386_GOT32
&& elf_hash_table (info)->dynamic_sections_created
@ -1340,11 +1478,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
case R_386_GOT32:
/* Relocation is to the entry for this symbol in the global
offset table. */
if (sgot == NULL)
{
sgot = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (sgot != NULL);
}
BFD_ASSERT (sgot != NULL);
if (h != NULL)
{
@ -1463,12 +1597,13 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
/* Relocation is to the entry for this symbol in the
procedure linkage table. */
/* Resolve a PLT32 reloc again a local symbol directly,
/* Resolve a PLT32 reloc against a local symbol directly,
without using the procedure linkage table. */
if (h == NULL)
break;
if (h->plt.offset == (bfd_vma) -1)
if (h->plt.offset == (bfd_vma) -1
|| splt == NULL)
{
/* We didn't make a PLT entry for this symbol. This
happens when statically linking PIC code, or when
@ -1476,12 +1611,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
break;
}
if (splt == NULL)
{
splt = bfd_get_section_by_name (dynobj, ".plt");
BFD_ASSERT (splt != NULL);
}
relocation = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
@ -1517,10 +1646,22 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
if (name == NULL)
return false;
BFD_ASSERT (strncmp (name, ".rel", 4) == 0
&& strcmp (bfd_get_section_name (input_bfd,
input_section),
name + 4) == 0);
if (strncmp (name, ".rel", 4) != 0
|| strcmp (bfd_get_section_name (input_bfd,
input_section),
name + 4) != 0)
{
if (input_bfd->my_archive)
(*_bfd_error_handler) (_("%s(%s): bad relocation section name `%s\'"),
bfd_get_filename (input_bfd->my_archive),
bfd_get_filename (input_bfd),
name);
else
(*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"),
bfd_get_filename (input_bfd),
name);
return false;
}
sreloc = bfd_get_section_by_name (dynobj, name);
BFD_ASSERT (sreloc != NULL);
@ -1748,17 +1889,21 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
+ sgot->output_offset
+ (h->got.offset &~ 1));
/* If this is a -Bsymbolic link, and the symbol is defined
locally, we just want to emit a RELATIVE reloc. Likewise if
the symbol was forced to be local because of a version file.
/* If this is a static link, or it is a -Bsymbolic link and the
symbol is defined locally or was forced to be local because
of a version file, 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->dynindx == -1)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
if (! elf_hash_table (info)->dynamic_sections_created
|| (info->shared
&& (info->symbolic || h->dynindx == -1)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
}
else
{
BFD_ASSERT((h->got.offset & 1) == 0);
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);
}
@ -1932,27 +2077,6 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
#define ELF_ARCH bfd_arch_i386
#define ELF_MACHINE_CODE EM_386
#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto elf_i386_info_to_howto
#define elf_info_to_howto_rel elf_i386_info_to_howto_rel
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
#define bfd_elf32_bfd_is_local_label_name \
elf_i386_is_local_label_name
#define elf_backend_create_dynamic_sections \
_bfd_elf_create_dynamic_sections
#define bfd_elf32_bfd_link_hash_table_create \
elf_i386_link_hash_table_create
#define elf_backend_check_relocs elf_i386_check_relocs
#define elf_backend_adjust_dynamic_symbol \
elf_i386_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
elf_i386_size_dynamic_sections
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_finish_dynamic_symbol \
elf_i386_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
elf_i386_finish_dynamic_sections
#define elf_backend_gc_mark_hook elf_i386_gc_mark_hook
#define elf_backend_gc_sweep_hook elf_i386_gc_sweep_hook
#define elf_backend_can_gc_sections 1
#define elf_backend_want_got_plt 1
@ -1961,4 +2085,22 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
#define elf_backend_got_header_size 12
#define elf_backend_plt_header_size PLT_ENTRY_SIZE
#define elf_info_to_howto elf_i386_info_to_howto
#define elf_info_to_howto_rel elf_i386_info_to_howto_rel
#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol
#define elf_backend_check_relocs elf_i386_check_relocs
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
#define elf_backend_finish_dynamic_sections elf_i386_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_i386_finish_dynamic_symbol
#define elf_backend_gc_mark_hook elf_i386_gc_mark_hook
#define elf_backend_gc_sweep_hook elf_i386_gc_sweep_hook
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
#include "elf32-target.h"