mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 20:43:45 +08:00
* elf-bfd.h (struct bfd_elf_section_data): Add "local_dynrel"
and "sreloc" fields. * elf32-i386.c (struct elf_i386_dyn_relocs): Add "sec", and "pc_count" fields. Remove "section" field. (elf_i386_check_relocs): Don't set DF_TEXTREL here. Don't allocate space for dynamic relocs here. Instead, record all needed dynamic relocs via dyn_relocs and local_dynrel. Cache pointer to "sreloc" section in elf_section_data. (elf_i386_gc_sweep_hook): Sweep dyn_relocs and local_dynrel. (allocate_plt_and_got_and_discard_relocs): Rename to allocate_dynrelocs. Allocate rather than discarding dyn relocs. (readonly_dynrelocs): New function. (elf_i386_size_dynamic_sections): Call readonly_dynrelocs. Rename "i" to "ibfd". Allocate space for local dyn relocs. (elf_i386_relocate_section): Make use of cached sreloc.
This commit is contained in:
parent
4f3379724d
commit
0c715baa72
@ -1,3 +1,21 @@
|
|||||||
|
2001-09-25 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf-bfd.h (struct bfd_elf_section_data): Add "local_dynrel"
|
||||||
|
and "sreloc" fields.
|
||||||
|
* elf32-i386.c (struct elf_i386_dyn_relocs): Add "sec", and
|
||||||
|
"pc_count" fields. Remove "section" field.
|
||||||
|
(elf_i386_check_relocs): Don't set DF_TEXTREL here. Don't
|
||||||
|
allocate space for dynamic relocs here. Instead, record all
|
||||||
|
needed dynamic relocs via dyn_relocs and local_dynrel. Cache
|
||||||
|
pointer to "sreloc" section in elf_section_data.
|
||||||
|
(elf_i386_gc_sweep_hook): Sweep dyn_relocs and local_dynrel.
|
||||||
|
(allocate_plt_and_got_and_discard_relocs): Rename to
|
||||||
|
allocate_dynrelocs. Allocate rather than discarding dyn relocs.
|
||||||
|
(readonly_dynrelocs): New function.
|
||||||
|
(elf_i386_size_dynamic_sections): Call readonly_dynrelocs.
|
||||||
|
Rename "i" to "ibfd". Allocate space for local dyn relocs.
|
||||||
|
(elf_i386_relocate_section): Make use of cached sreloc.
|
||||||
|
|
||||||
2001-09-24 Alan Modra <amodra@bigpond.net.au>
|
2001-09-24 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* elf-bfd.h (elf_backend_reloc_type_class): Pass in the entire
|
* elf-bfd.h (elf_backend_reloc_type_class): Pass in the entire
|
||||||
|
@ -737,43 +737,63 @@ struct bfd_elf_section_data
|
|||||||
{
|
{
|
||||||
/* The ELF header for this section. */
|
/* The ELF header for this section. */
|
||||||
Elf_Internal_Shdr this_hdr;
|
Elf_Internal_Shdr this_hdr;
|
||||||
|
|
||||||
/* The ELF header for the reloc section associated with this
|
/* The ELF header for the reloc section associated with this
|
||||||
section, if any. */
|
section, if any. */
|
||||||
Elf_Internal_Shdr rel_hdr;
|
Elf_Internal_Shdr rel_hdr;
|
||||||
|
|
||||||
/* If there is a second reloc section associated with this section,
|
/* If there is a second reloc section associated with this section,
|
||||||
as can happen on Irix 6, this field points to the header. */
|
as can happen on Irix 6, this field points to the header. */
|
||||||
Elf_Internal_Shdr *rel_hdr2;
|
Elf_Internal_Shdr *rel_hdr2;
|
||||||
|
|
||||||
/* The number of relocations currently assigned to REL_HDR. */
|
/* The number of relocations currently assigned to REL_HDR. */
|
||||||
unsigned int rel_count;
|
unsigned int rel_count;
|
||||||
|
|
||||||
/* The number of relocations currently assigned to REL_HDR2. */
|
/* The number of relocations currently assigned to REL_HDR2. */
|
||||||
unsigned int rel_count2;
|
unsigned int rel_count2;
|
||||||
|
|
||||||
|
/* The number of dynamic relocs copied for local symbols. */
|
||||||
|
unsigned int local_dynrel;
|
||||||
|
|
||||||
|
/* A pointer to the bfd section used for dynamic relocs. */
|
||||||
|
asection *sreloc;
|
||||||
|
|
||||||
/* The ELF section number of this section. Only used for an output
|
/* The ELF section number of this section. Only used for an output
|
||||||
file. */
|
file. */
|
||||||
int this_idx;
|
int this_idx;
|
||||||
|
|
||||||
/* The ELF section number of the reloc section indicated by
|
/* The ELF section number of the reloc section indicated by
|
||||||
REL_HDR if any. Only used for an output file. */
|
REL_HDR if any. Only used for an output file. */
|
||||||
int rel_idx;
|
int rel_idx;
|
||||||
|
|
||||||
/* The ELF section number of the reloc section indicated by
|
/* The ELF section number of the reloc section indicated by
|
||||||
REL_HDR2 if any. Only used for an output file. */
|
REL_HDR2 if any. Only used for an output file. */
|
||||||
int rel_idx2;
|
int rel_idx2;
|
||||||
|
|
||||||
/* Used by the backend linker to store the symbol hash table entries
|
/* Used by the backend linker to store the symbol hash table entries
|
||||||
associated with relocs against global symbols. */
|
associated with relocs against global symbols. */
|
||||||
struct elf_link_hash_entry **rel_hashes;
|
struct elf_link_hash_entry **rel_hashes;
|
||||||
|
|
||||||
/* A pointer to the swapped relocs. If the section uses REL relocs,
|
/* A pointer to the swapped relocs. If the section uses REL relocs,
|
||||||
rather than RELA, all the r_addend fields will be zero. This
|
rather than RELA, all the r_addend fields will be zero. This
|
||||||
pointer may be NULL. It is used by the backend linker. */
|
pointer may be NULL. It is used by the backend linker. */
|
||||||
Elf_Internal_Rela *relocs;
|
Elf_Internal_Rela *relocs;
|
||||||
|
|
||||||
/* Used by the backend linker when generating a shared library to
|
/* Used by the backend linker when generating a shared library to
|
||||||
record the dynamic symbol index for a section symbol
|
record the dynamic symbol index for a section symbol
|
||||||
corresponding to this section. A value of 0 means that there is
|
corresponding to this section. A value of 0 means that there is
|
||||||
no dynamic symbol for this section. */
|
no dynamic symbol for this section. */
|
||||||
long dynindx;
|
long dynindx;
|
||||||
|
|
||||||
/* A pointer used for .stab linking optimizations. */
|
/* A pointer used for .stab linking optimizations. */
|
||||||
PTR stab_info;
|
PTR stab_info;
|
||||||
|
|
||||||
/* A pointer used for SEC_MERGE optimizations. */
|
/* A pointer used for SEC_MERGE optimizations. */
|
||||||
PTR merge_info;
|
PTR merge_info;
|
||||||
|
|
||||||
/* A pointer available for the processor specific ELF backend. */
|
/* A pointer available for the processor specific ELF backend. */
|
||||||
PTR tdata;
|
PTR tdata;
|
||||||
|
|
||||||
/* Nonzero if this section uses RELA relocations, rather than REL. */
|
/* Nonzero if this section uses RELA relocations, rather than REL. */
|
||||||
unsigned int use_rela_p:1;
|
unsigned int use_rela_p:1;
|
||||||
};
|
};
|
||||||
|
267
bfd/elf32-i386.c
267
bfd/elf32-i386.c
@ -49,7 +49,9 @@ static boolean elf_i386_gc_sweep_hook
|
|||||||
const Elf_Internal_Rela *));
|
const Elf_Internal_Rela *));
|
||||||
static boolean elf_i386_adjust_dynamic_symbol
|
static boolean elf_i386_adjust_dynamic_symbol
|
||||||
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
|
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
|
||||||
static boolean allocate_plt_and_got_and_discard_relocs
|
static boolean allocate_dynrelocs
|
||||||
|
PARAMS ((struct elf_link_hash_entry *, PTR));
|
||||||
|
static boolean readonly_dynrelocs
|
||||||
PARAMS ((struct elf_link_hash_entry *, PTR));
|
PARAMS ((struct elf_link_hash_entry *, PTR));
|
||||||
static boolean elf_i386_size_dynamic_sections
|
static boolean elf_i386_size_dynamic_sections
|
||||||
PARAMS ((bfd *, struct bfd_link_info *));
|
PARAMS ((bfd *, struct bfd_link_info *));
|
||||||
@ -378,12 +380,16 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
|
|||||||
|
|
||||||
struct elf_i386_dyn_relocs
|
struct elf_i386_dyn_relocs
|
||||||
{
|
{
|
||||||
/* Next section. */
|
|
||||||
struct elf_i386_dyn_relocs *next;
|
struct elf_i386_dyn_relocs *next;
|
||||||
/* A section in dynobj. */
|
|
||||||
asection *section;
|
/* The input section of the reloc. */
|
||||||
/* Number of relocs copied in this section. */
|
asection *sec;
|
||||||
|
|
||||||
|
/* Total number of relocs copied for the input section. */
|
||||||
bfd_size_type count;
|
bfd_size_type count;
|
||||||
|
|
||||||
|
/* Number of pc-relative relocs copied for the input section. */
|
||||||
|
bfd_size_type pc_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* i386 ELF linker hash entry. */
|
/* i386 ELF linker hash entry. */
|
||||||
@ -392,7 +398,7 @@ struct elf_i386_link_hash_entry
|
|||||||
{
|
{
|
||||||
struct elf_link_hash_entry root;
|
struct elf_link_hash_entry root;
|
||||||
|
|
||||||
/* Number of PC relative relocs copied for this symbol. */
|
/* Track dynamic relocs copied for this symbol. */
|
||||||
struct elf_i386_dyn_relocs *dyn_relocs;
|
struct elf_i386_dyn_relocs *dyn_relocs;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -743,9 +749,9 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
|| strcmp (bfd_get_section_name (abfd, sec),
|
|| strcmp (bfd_get_section_name (abfd, sec),
|
||||||
name + 4) != 0)
|
name + 4) != 0)
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"),
|
(*_bfd_error_handler)
|
||||||
bfd_archive_filename (abfd),
|
(_("%s: bad relocation section name `%s\'"),
|
||||||
name);
|
bfd_archive_filename (abfd), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
sreloc = bfd_get_section_by_name (dynobj, name);
|
sreloc = bfd_get_section_by_name (dynobj, name);
|
||||||
@ -763,32 +769,20 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
|
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (sec->flags & SEC_READONLY)
|
elf_section_data (sec)->sreloc = sreloc;
|
||||||
info->flags |= DF_TEXTREL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sreloc->_raw_size += sizeof (Elf32_External_Rel);
|
/* If this is a global symbol, we count the number of
|
||||||
|
relocations we need for this symbol. */
|
||||||
/* If this is a global symbol, we count the number of PC
|
if (h != NULL)
|
||||||
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 (!info->shared
|
|
||||||
|| (h != NULL
|
|
||||||
&& ELF32_R_TYPE (rel->r_info) == R_386_PC32))
|
|
||||||
{
|
{
|
||||||
struct elf_i386_link_hash_entry *eh;
|
struct elf_i386_link_hash_entry *eh;
|
||||||
struct elf_i386_dyn_relocs *p;
|
struct elf_i386_dyn_relocs *p;
|
||||||
|
|
||||||
eh = (struct elf_i386_link_hash_entry *) h;
|
eh = (struct elf_i386_link_hash_entry *) h;
|
||||||
|
p = eh->dyn_relocs;
|
||||||
|
|
||||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
if (p == NULL || p->sec != sec)
|
||||||
if (p->section == sreloc)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
{
|
||||||
p = ((struct elf_i386_dyn_relocs *)
|
p = ((struct elf_i386_dyn_relocs *)
|
||||||
bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
|
bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
|
||||||
@ -796,11 +790,19 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
return false;
|
return false;
|
||||||
p->next = eh->dyn_relocs;
|
p->next = eh->dyn_relocs;
|
||||||
eh->dyn_relocs = p;
|
eh->dyn_relocs = p;
|
||||||
p->section = sreloc;
|
p->sec = sec;
|
||||||
p->count = 0;
|
p->count = 0;
|
||||||
|
p->pc_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
++p->count;
|
p->count += 1;
|
||||||
|
if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
|
||||||
|
p->pc_count += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Track dynamic relocs needed for local syms too. */
|
||||||
|
elf_section_data (sec)->local_dynrel += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -893,6 +895,8 @@ elf_i386_gc_sweep_hook (abfd, info, sec, relocs)
|
|||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
|
|
||||||
|
elf_section_data (sec)->local_dynrel = 0;
|
||||||
|
|
||||||
dynobj = elf_hash_table (info)->dynobj;
|
dynobj = elf_hash_table (info)->dynobj;
|
||||||
if (dynobj == NULL)
|
if (dynobj == NULL)
|
||||||
return true;
|
return true;
|
||||||
@ -924,9 +928,32 @@ elf_i386_gc_sweep_hook (abfd, info, sec, relocs)
|
|||||||
|
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
if (info->shared)
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
|
if (r_symndx >= symtab_hdr->sh_info)
|
||||||
|
{
|
||||||
|
struct elf_i386_link_hash_entry *eh;
|
||||||
|
struct elf_i386_dyn_relocs **pp;
|
||||||
|
struct elf_i386_dyn_relocs *p;
|
||||||
|
|
||||||
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
|
|
||||||
|
if (!info->shared && h->plt.refcount > 0)
|
||||||
|
h->plt.refcount -= 1;
|
||||||
|
|
||||||
|
eh = (struct elf_i386_link_hash_entry *) h;
|
||||||
|
|
||||||
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
|
||||||
|
if (p->sec == sec)
|
||||||
|
{
|
||||||
|
if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
|
||||||
|
p->pc_count -= 1;
|
||||||
|
p->count -= 1;
|
||||||
|
if (p->count == 0)
|
||||||
|
*pp = p->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
/* Fall through. */
|
|
||||||
|
|
||||||
case R_386_PLT32:
|
case R_386_PLT32:
|
||||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
@ -1087,12 +1114,10 @@ elf_i386_adjust_dynamic_symbol (info, h)
|
|||||||
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
|
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
|
||||||
|
|
||||||
/* Allocate space in .plt, .got and associated reloc sections for
|
/* Allocate space in .plt, .got and associated reloc sections for
|
||||||
global syms. Also discards space allocated for relocs in the
|
dynamic relocs. */
|
||||||
check_relocs function that we subsequently have found to be
|
|
||||||
unneeded. */
|
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
allocate_plt_and_got_and_discard_relocs (h, inf)
|
allocate_dynrelocs (h, inf)
|
||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
PTR inf;
|
PTR inf;
|
||||||
{
|
{
|
||||||
@ -1100,6 +1125,7 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
|
|||||||
struct elf_i386_link_hash_table *htab;
|
struct elf_i386_link_hash_table *htab;
|
||||||
asection *s;
|
asection *s;
|
||||||
struct elf_i386_link_hash_entry *eh;
|
struct elf_i386_link_hash_entry *eh;
|
||||||
|
struct elf_i386_dyn_relocs *p;
|
||||||
|
|
||||||
if (h->root.type == bfd_link_hash_indirect
|
if (h->root.type == bfd_link_hash_indirect
|
||||||
|| h->root.type == bfd_link_hash_warning)
|
|| h->root.type == bfd_link_hash_warning)
|
||||||
@ -1191,19 +1217,42 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
|
|||||||
else
|
else
|
||||||
h->got.offset = (bfd_vma) -1;
|
h->got.offset = (bfd_vma) -1;
|
||||||
|
|
||||||
/* In the shared -Bsymbolic case, discard space allocated for
|
|
||||||
dynamic relocs against symbols which turn out to be defined
|
|
||||||
in regular objects. For the normal shared case, discard space
|
|
||||||
for relocs that have become local due to symbol visibility
|
|
||||||
changes. For the non-shared case, discard space for symbols
|
|
||||||
which turn out to need copy relocs or are not dynamic. */
|
|
||||||
|
|
||||||
eh = (struct elf_i386_link_hash_entry *) h;
|
eh = (struct elf_i386_link_hash_entry *) h;
|
||||||
if (eh->dyn_relocs == NULL)
|
if (eh->dyn_relocs == NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!info->shared
|
/* In the shared -Bsymbolic case, discard space allocated for
|
||||||
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
|
dynamic pc-relative relocs against symbols which turn out to be
|
||||||
|
defined in regular objects. For the normal shared case, discard
|
||||||
|
space for relocs that have become local due to symbol visibility
|
||||||
|
changes. */
|
||||||
|
|
||||||
|
if (info->shared)
|
||||||
|
{
|
||||||
|
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
|
||||||
|
&& ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
|
||||||
|
|| info->symbolic))
|
||||||
|
{
|
||||||
|
struct elf_i386_dyn_relocs **pp;
|
||||||
|
|
||||||
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
||||||
|
{
|
||||||
|
p->count -= p->pc_count;
|
||||||
|
p->pc_count = 0;
|
||||||
|
if (p->count == 0)
|
||||||
|
*pp = p->next;
|
||||||
|
else
|
||||||
|
pp = &p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* For the non-shared case, discard space for relocs against
|
||||||
|
symbols which turn out to need copy relocs or are not
|
||||||
|
dynamic. */
|
||||||
|
|
||||||
|
if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
|
||||||
&& (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
|
&& (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
|
||||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
|
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
|
||||||
|| (htab->root.dynamic_sections_created
|
|| (htab->root.dynamic_sections_created
|
||||||
@ -1219,22 +1268,52 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If that succeeded, we know we'll be keeping all the relocs. */
|
/* If that succeeded, we know we'll be keeping all the
|
||||||
|
relocs. */
|
||||||
if (h->dynindx != -1)
|
if (h->dynindx != -1)
|
||||||
|
goto keep;
|
||||||
|
}
|
||||||
|
|
||||||
|
eh->dyn_relocs = NULL;
|
||||||
|
|
||||||
|
keep:
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, allocate space. */
|
||||||
|
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
asection *sreloc = elf_section_data (p->sec)->sreloc;
|
||||||
|
sreloc->_raw_size += p->count * sizeof (Elf32_External_Rel);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info->shared
|
/* Find any dynamic relocs that apply to read-only sections. */
|
||||||
|| ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
|
|
||||||
&& ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
|
static boolean
|
||||||
|| info->symbolic)))
|
readonly_dynrelocs (h, inf)
|
||||||
|
struct elf_link_hash_entry *h;
|
||||||
|
PTR inf;
|
||||||
{
|
{
|
||||||
struct elf_i386_dyn_relocs *c;
|
struct elf_i386_link_hash_entry *eh;
|
||||||
|
struct elf_i386_dyn_relocs *p;
|
||||||
|
|
||||||
for (c = eh->dyn_relocs; c != NULL; c = c->next)
|
eh = (struct elf_i386_link_hash_entry *) h;
|
||||||
c->section->_raw_size -= c->count * sizeof (Elf32_External_Rel);
|
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
asection *s = p->sec->output_section;
|
||||||
|
|
||||||
|
if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
||||||
|
{
|
||||||
|
struct bfd_link_info *info = (struct bfd_link_info *) inf;
|
||||||
|
|
||||||
|
info->flags |= DF_TEXTREL;
|
||||||
|
|
||||||
|
/* Not an error, just cut short the traversal. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1249,7 +1328,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
asection *s;
|
asection *s;
|
||||||
boolean relocs;
|
boolean relocs;
|
||||||
bfd *i;
|
bfd *ibfd;
|
||||||
|
|
||||||
htab = elf_i386_hash_table (info);
|
htab = elf_i386_hash_table (info);
|
||||||
dynobj = htab->root.dynobj;
|
dynobj = htab->root.dynobj;
|
||||||
@ -1269,8 +1348,9 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up .got offsets for local syms. */
|
/* Set up .got offsets for local syms, and space for local dynamic
|
||||||
for (i = info->input_bfds; i; i = i->link_next)
|
relocs. */
|
||||||
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
||||||
{
|
{
|
||||||
bfd_signed_vma *local_got;
|
bfd_signed_vma *local_got;
|
||||||
bfd_signed_vma *end_local_got;
|
bfd_signed_vma *end_local_got;
|
||||||
@ -1278,14 +1358,25 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
asection *srel;
|
asection *srel;
|
||||||
|
|
||||||
if (bfd_get_flavour (i) != bfd_target_elf_flavour)
|
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
local_got = elf_local_got_refcounts (i);
|
for (s = ibfd->sections; s != NULL; s = s->next)
|
||||||
|
{
|
||||||
|
bfd_size_type count = elf_section_data (s)->local_dynrel;
|
||||||
|
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
srel = elf_section_data (s)->sreloc;
|
||||||
|
srel->_raw_size += count * sizeof (Elf32_External_Rel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local_got = elf_local_got_refcounts (ibfd);
|
||||||
if (!local_got)
|
if (!local_got)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
symtab_hdr = &elf_tdata (i)->symtab_hdr;
|
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
||||||
locsymcount = symtab_hdr->sh_info;
|
locsymcount = symtab_hdr->sh_info;
|
||||||
end_local_got = local_got + locsymcount;
|
end_local_got = local_got + locsymcount;
|
||||||
s = htab->sgot;
|
s = htab->sgot;
|
||||||
@ -1304,11 +1395,9 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate global sym .plt and .got entries. Also discard all
|
/* Allocate global sym .plt and .got entries, and space for global
|
||||||
unneeded relocs. */
|
sym dynamic relocs. */
|
||||||
elf_link_hash_traverse (&htab->root,
|
elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
|
||||||
allocate_plt_and_got_and_discard_relocs,
|
|
||||||
(PTR) info);
|
|
||||||
|
|
||||||
/* We now have determined the sizes of the various dynamic sections.
|
/* We now have determined the sizes of the various dynamic sections.
|
||||||
Allocate memory for them. */
|
Allocate memory for them. */
|
||||||
@ -1402,7 +1491,10 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
|| !add_dynamic_entry (DT_RELSZ, 0)
|
|| !add_dynamic_entry (DT_RELSZ, 0)
|
||||||
|| !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel)))
|
|| !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel)))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
/* If any dynamic relocs apply to a read-only section,
|
||||||
|
then we need a DT_TEXTREL entry. */
|
||||||
|
elf_link_hash_traverse (&htab->root, readonly_dynrelocs, (PTR) info);
|
||||||
|
|
||||||
if ((info->flags & DF_TEXTREL) != 0)
|
if ((info->flags & DF_TEXTREL) != 0)
|
||||||
{
|
{
|
||||||
@ -1410,6 +1502,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#undef add_dynamic_entry
|
#undef add_dynamic_entry
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1434,7 +1527,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
struct elf_link_hash_entry **sym_hashes;
|
struct elf_link_hash_entry **sym_hashes;
|
||||||
bfd_vma *local_got_offsets;
|
bfd_vma *local_got_offsets;
|
||||||
asection *sreloc;
|
|
||||||
Elf_Internal_Rela *rel;
|
Elf_Internal_Rela *rel;
|
||||||
Elf_Internal_Rela *relend;
|
Elf_Internal_Rela *relend;
|
||||||
|
|
||||||
@ -1444,7 +1536,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
sym_hashes = elf_sym_hashes (input_bfd);
|
sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
local_got_offsets = elf_local_got_offsets (input_bfd);
|
local_got_offsets = elf_local_got_offsets (input_bfd);
|
||||||
|
|
||||||
sreloc = NULL;
|
|
||||||
rel = relocs;
|
rel = relocs;
|
||||||
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
||||||
for (; rel < relend; rel++)
|
for (; rel < relend; rel++)
|
||||||
@ -1712,38 +1803,13 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
{
|
{
|
||||||
Elf_Internal_Rel outrel;
|
Elf_Internal_Rel outrel;
|
||||||
boolean skip, relocate;
|
boolean skip, relocate;
|
||||||
|
asection *sreloc;
|
||||||
|
Elf32_External_Rel *loc;
|
||||||
|
|
||||||
/* When generating a shared object, these relocations
|
/* When generating a shared object, these relocations
|
||||||
are copied into the output file to be resolved at run
|
are copied into the output file to be resolved at run
|
||||||
time. */
|
time. */
|
||||||
|
|
||||||
if (sreloc == NULL)
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
name = (bfd_elf_string_from_elf_section
|
|
||||||
(input_bfd,
|
|
||||||
elf_elfheader (input_bfd)->e_shstrndx,
|
|
||||||
elf_section_data (input_section)->rel_hdr.sh_name));
|
|
||||||
if (name == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (strncmp (name, ".rel", 4) != 0
|
|
||||||
|| strcmp (bfd_get_section_name (input_bfd,
|
|
||||||
input_section),
|
|
||||||
name + 4) != 0)
|
|
||||||
{
|
|
||||||
(*_bfd_error_handler)
|
|
||||||
(_("%s: bad relocation section name `%s\'"),
|
|
||||||
bfd_archive_filename (input_bfd), name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sreloc = bfd_get_section_by_name (dynobj, name);
|
|
||||||
if (sreloc == NULL)
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
skip = false;
|
skip = false;
|
||||||
|
|
||||||
if (elf_section_data (input_section)->stab_info == NULL)
|
if (elf_section_data (input_section)->stab_info == NULL)
|
||||||
@ -1786,11 +1852,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bfd_elf32_swap_reloc_out (output_bfd, &outrel,
|
sreloc = elf_section_data (input_section)->sreloc;
|
||||||
(((Elf32_External_Rel *)
|
if (sreloc == NULL)
|
||||||
sreloc->contents)
|
abort ();
|
||||||
+ sreloc->reloc_count));
|
|
||||||
++sreloc->reloc_count;
|
loc = ((Elf32_External_Rel *) sreloc->contents
|
||||||
|
+ sreloc->reloc_count);
|
||||||
|
sreloc->reloc_count += 1;
|
||||||
|
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
|
||||||
|
|
||||||
/* If this reloc is against an external symbol, we do
|
/* If this reloc is against an external symbol, we do
|
||||||
not want to fiddle with the addend. Otherwise, we
|
not want to fiddle with the addend. Otherwise, we
|
||||||
|
Loading…
Reference in New Issue
Block a user