Fix the ELF linker to not require an interpreter if no dynamic
objects were seen, even when linking PIC code. * libelf.h (ELF_LINK_HASH_NEEDS_PLT): Define. (struct elf_link_hash_table): Add field dynamic_sections_created. * elfcode.h (elf_link_record_dynamic_symbol): Create dynstr if it doesn't already exist. (elf_link_add_object_symbols): Create dynamic sections based on dynamic_sections_created field, not dynobj field. Don't bother to set dynobj. (elf_link_create_dynamic_sections): If dynamic sections were already created, don't do anything. If dynobj is already set, use it; otherwise, set it to the bfd argument. Don't initialize dynsymcount. Only create dynstr if it does not exist. Set dynamic_sections_created to true. (NAME(bfd_elf,size_dynamic_sections)): Skip most of this function if no dynamic objects were seen. (elf_adjust_dynamic_symbol): If a symbol has the ELF_LINK_HASH_NEEDS_PLT flag set, let the backend adjust it. (elf_bfd_final_link): Change most decisions based on dynobj to check dynamic_sections_created instead. (elf_link_output_extsym): Only handle dynamic symbols if a dynamic object was seen. * elf.c (_bfd_elf_link_hash_table_init): Initialize new field dynamic_sections_created. Set dynsymcount to 1, not 0. * elf32-i386.c (elf_i386_create_dynamic_sections): Call elf_i386_create_got_section rather than creating the .got and .got.plt sections. (elf_i386_create_got_section): New static function. (elf_i386_check_relocs): Just call elf_i386_create_got_section if a GOT table is needed, not bfd_elf32_link_create_dynamic_sections. Only create the .rel.got section, and only make space for a reloc, for a global symbol or when generating a shared object. For a R_386_PLT32 reloc, just set the ELF_LINK_HASH_NEEDS_PLT flag. (elf_i386_adjust_dynamic_symbol): Rework initial assertion to permit ELF_LINK_HASH_NEEDS_PLT non dynamic symbols. Create a procedure linkage table entry for such symbols. But, if no dynamic objects were seen, never create a PLT entry. (elf_i386_size_dynamic_sections): If no dynamic objects were seen, skip most of this function, and force the size of the .rel.got section to zero. (elf_i386_relocate_section): For a R_386_GOT32 reloc against a global symbol when no dynamic object was seen, initialize the contents of the .got section. For a R_386_GOT32 against a local symbol, only create a R_386_RELATIVE reloc when generating a shared object. Treat a R_386_PLT32 reloc against a symbol for which we did not create a PLT entry as a R_386_PC32 reloc. (elf_i386_finish_dynamic_sections): Only fiddle with the dynamic entries and the PLT if we saw a dynamic object. * elf32-sparc.c (elf_sparc_howto_table): Fix R_SPARC_PC22 by setting rightshift to 10. Fix R_SPARC_WPLT20 by setting rightshift to 2, size to 2, bitsize to 30, and dst_mask to 0x3fffffff. (elf32_sparc_create_dynamic_sections): Don't set the size of the .plt section. Call elf32_sparc_create_got_section rather than creating the .got section. (elf32_sparc_check_relocs): Call elf32_sparc_create_got_section if a GOT table is needed, not bfd_elf32_link_create_dynamic_sections. Only create the .rela.got section, and only make space for a reloc, for a global symbol or when generating a shared object. Set the alignment of the .rela.got section to 2. For a R_SPARC_WPLT30 reloc, just set the ELF_LINK_HASH_NEEDS_PLT flag. (elf32_sparc_adjust_dynamic_symbol): Rework initial assertion to permit ELF_LINK_HASH_NEDS_PLT non dynamic symbols. Create a procedure linkage table for such symbols. But, if no dynamic objects were seen, never create a PLT entry. Initialize the size of the .plt section. (elf32_sparc_size_dynamic_sections): If no dynamic objects were seen, skip most of this function, and force the size of the .rela.got section to zero. Strip empty reloc sections, and strip an empty .plt section. (elf32_sparc_relocate_section): For a GOT reloc against a global symbol when no dynamic object was seen, initialize the contents of the .got section. For a GOT reloc against a local symbol, only create a R_SPARC_RELATIVE reloc when generating a shared object. Treat a R_SPARC_WPLT30 reloc against a symbol for which we did not create a PLT entry as a R_SPARC_WDISP30 reloc. (elf32_sparc_finish_dynamic_sections): Only fiddle with the dynamic entries and the PLT if we saw a dynamic object.
This commit is contained in:
parent
6b55e5e3b9
commit
12662be4fe
5 changed files with 944 additions and 610 deletions
|
@ -1,3 +1,84 @@
|
|||
Fri Oct 21 17:13:07 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
|
||||
|
||||
Fix the ELF linker to not require an interpreter if no dynamic
|
||||
objects were seen, even when linking PIC code.
|
||||
* libelf.h (ELF_LINK_HASH_NEEDS_PLT): Define.
|
||||
(struct elf_link_hash_table): Add field dynamic_sections_created.
|
||||
* elfcode.h (elf_link_record_dynamic_symbol): Create dynstr if it
|
||||
doesn't already exist.
|
||||
(elf_link_add_object_symbols): Create dynamic sections based on
|
||||
dynamic_sections_created field, not dynobj field. Don't bother to
|
||||
set dynobj.
|
||||
(elf_link_create_dynamic_sections): If dynamic sections were
|
||||
already created, don't do anything. If dynobj is already set, use
|
||||
it; otherwise, set it to the bfd argument. Don't initialize
|
||||
dynsymcount. Only create dynstr if it does not exist. Set
|
||||
dynamic_sections_created to true.
|
||||
(NAME(bfd_elf,size_dynamic_sections)): Skip most of this function
|
||||
if no dynamic objects were seen.
|
||||
(elf_adjust_dynamic_symbol): If a symbol has the
|
||||
ELF_LINK_HASH_NEEDS_PLT flag set, let the backend adjust it.
|
||||
(elf_bfd_final_link): Change most decisions based on dynobj to
|
||||
check dynamic_sections_created instead.
|
||||
(elf_link_output_extsym): Only handle dynamic symbols if a dynamic
|
||||
object was seen.
|
||||
* elf.c (_bfd_elf_link_hash_table_init): Initialize new field
|
||||
dynamic_sections_created. Set dynsymcount to 1, not 0.
|
||||
* elf32-i386.c (elf_i386_create_dynamic_sections): Call
|
||||
elf_i386_create_got_section rather than creating the .got and
|
||||
.got.plt sections.
|
||||
(elf_i386_create_got_section): New static function.
|
||||
(elf_i386_check_relocs): Just call elf_i386_create_got_section if
|
||||
a GOT table is needed, not bfd_elf32_link_create_dynamic_sections.
|
||||
Only create the .rel.got section, and only make space for a reloc,
|
||||
for a global symbol or when generating a shared object. For a
|
||||
R_386_PLT32 reloc, just set the ELF_LINK_HASH_NEEDS_PLT flag.
|
||||
(elf_i386_adjust_dynamic_symbol): Rework initial assertion to
|
||||
permit ELF_LINK_HASH_NEEDS_PLT non dynamic symbols. Create a
|
||||
procedure linkage table entry for such symbols. But, if no
|
||||
dynamic objects were seen, never create a PLT entry.
|
||||
(elf_i386_size_dynamic_sections): If no dynamic objects were seen,
|
||||
skip most of this function, and force the size of the .rel.got
|
||||
section to zero.
|
||||
(elf_i386_relocate_section): For a R_386_GOT32 reloc against a global
|
||||
symbol when no dynamic object was seen, initialize the contents of
|
||||
the .got section. For a R_386_GOT32 against a local symbol, only
|
||||
create a R_386_RELATIVE reloc when generating a shared object.
|
||||
Treat a R_386_PLT32 reloc against a symbol for which we did not
|
||||
create a PLT entry as a R_386_PC32 reloc.
|
||||
(elf_i386_finish_dynamic_sections): Only fiddle with the dynamic
|
||||
entries and the PLT if we saw a dynamic object.
|
||||
* elf32-sparc.c (elf_sparc_howto_table): Fix R_SPARC_PC22 by
|
||||
setting rightshift to 10. Fix R_SPARC_WPLT20 by setting
|
||||
rightshift to 2, size to 2, bitsize to 30, and dst_mask to
|
||||
0x3fffffff.
|
||||
(elf32_sparc_create_dynamic_sections): Don't set the size of the
|
||||
.plt section. Call elf32_sparc_create_got_section rather than
|
||||
creating the .got section.
|
||||
(elf32_sparc_check_relocs): Call elf32_sparc_create_got_section if
|
||||
a GOT table is needed, not bfd_elf32_link_create_dynamic_sections.
|
||||
Only create the .rela.got section, and only make space for a
|
||||
reloc, for a global symbol or when generating a shared object.
|
||||
Set the alignment of the .rela.got section to 2. For a
|
||||
R_SPARC_WPLT30 reloc, just set the ELF_LINK_HASH_NEEDS_PLT flag.
|
||||
(elf32_sparc_adjust_dynamic_symbol): Rework initial assertion to
|
||||
permit ELF_LINK_HASH_NEDS_PLT non dynamic symbols. Create a
|
||||
procedure linkage table for such symbols. But, if no dynamic
|
||||
objects were seen, never create a PLT entry. Initialize the size
|
||||
of the .plt section.
|
||||
(elf32_sparc_size_dynamic_sections): If no dynamic objects were
|
||||
seen, skip most of this function, and force the size of the
|
||||
.rela.got section to zero. Strip empty reloc sections, and strip
|
||||
an empty .plt section.
|
||||
(elf32_sparc_relocate_section): For a GOT reloc against a global
|
||||
symbol when no dynamic object was seen, initialize the contents of
|
||||
the .got section. For a GOT reloc against a local symbol, only
|
||||
create a R_SPARC_RELATIVE reloc when generating a shared object.
|
||||
Treat a R_SPARC_WPLT30 reloc against a symbol for which we did not
|
||||
create a PLT entry as a R_SPARC_WDISP30 reloc.
|
||||
(elf32_sparc_finish_dynamic_sections): Only fiddle with the
|
||||
dynamic entries and the PLT if we saw a dynamic object.
|
||||
|
||||
Thu Oct 20 13:28:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
|
||||
|
||||
* elfcode.h (elf_map_symbols): Don't worry about section symbols
|
||||
|
|
555
bfd/elf32-i386.c
555
bfd/elf32-i386.c
|
@ -31,6 +31,8 @@ static void elf_i386_info_to_howto_rel
|
|||
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
|
||||
static boolean elf_i386_create_dynamic_sections
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static boolean elf_i386_create_got_section
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static boolean elf_i386_check_relocs
|
||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||
const Elf_Internal_Rela *));
|
||||
|
@ -269,39 +271,9 @@ elf_i386_create_dynamic_sections (abfd, info)
|
|||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
|
||||
s = bfd_make_section (abfd, ".got");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
if (! elf_i386_create_got_section (abfd, info))
|
||||
return false;
|
||||
|
||||
s = bfd_make_section (abfd, ".got.plt");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
|
||||
/* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
|
||||
.got.plt section, which will be placed at the start of the output
|
||||
.got section. We don't do this in the linker script because we
|
||||
don't want to define the symbol if we are not creating a global
|
||||
offset table. */
|
||||
h = NULL;
|
||||
if (! (_bfd_generic_link_add_one_symbol
|
||||
(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, (bfd_vma) 0,
|
||||
(const char *) NULL, false, get_elf_backend_data (abfd)->collect,
|
||||
(struct bfd_link_hash_entry **) &h)))
|
||||
return false;
|
||||
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
|
||||
h->type = STT_OBJECT;
|
||||
|
||||
if (info->shared
|
||||
&& ! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
|
||||
/* The first three global offset table entries are reserved. */
|
||||
s->_raw_size += 3 * 4;
|
||||
|
||||
/* The .dynbss section is a place to put symbols which are defined
|
||||
by dynamic objects, are referenced by regular objects, and are
|
||||
not functions. We must allocate space for them in the process
|
||||
|
@ -336,6 +308,61 @@ elf_i386_create_dynamic_sections (abfd, info)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Create the .got section to hold the global offset table, and the
|
||||
.got.plt section to hold procedure linkage table GOT entries. The
|
||||
linker script will put .got.plt into the output .got section. */
|
||||
|
||||
static boolean
|
||||
elf_i386_create_got_section (abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
flagword flags;
|
||||
register asection *s;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
/* This function may be called more than once. */
|
||||
if (bfd_get_section_by_name (abfd, ".got") != NULL)
|
||||
return true;
|
||||
|
||||
flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
|
||||
|
||||
s = bfd_make_section (abfd, ".got");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
|
||||
s = bfd_make_section (abfd, ".got.plt");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
|
||||
/* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
|
||||
.got.plt section, which will be placed at the start of the output
|
||||
.got section. We don't do this in the linker script because we
|
||||
don't want to define the symbol if we are not creating a global
|
||||
offset table. */
|
||||
h = NULL;
|
||||
if (! (_bfd_generic_link_add_one_symbol
|
||||
(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, (bfd_vma) 0,
|
||||
(const char *) NULL, false, get_elf_backend_data (abfd)->collect,
|
||||
(struct bfd_link_hash_entry **) &h)))
|
||||
return false;
|
||||
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
|
||||
h->type = STT_OBJECT;
|
||||
|
||||
if (info->shared
|
||||
&& ! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
|
||||
/* The first three global offset table entries are reserved. */
|
||||
s->_raw_size += 3 * 4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Look through the relocs for a section during the first phase, and
|
||||
allocate space in the global offset table or procedure linkage
|
||||
table. */
|
||||
|
@ -355,9 +382,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
const Elf_Internal_Rela *rel_end;
|
||||
asection *sgot;
|
||||
asection *srelgot;
|
||||
asection *splt;
|
||||
asection *sgotplt;
|
||||
asection *srelplt;
|
||||
asection *sreloc;
|
||||
|
||||
if (info->relocateable)
|
||||
|
@ -370,9 +394,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
|
||||
sgot = NULL;
|
||||
srelgot = NULL;
|
||||
splt = NULL;
|
||||
sgotplt = NULL;
|
||||
srelplt = NULL;
|
||||
sreloc = NULL;
|
||||
|
||||
rel_end = relocs + sec->reloc_count;
|
||||
|
@ -388,20 +409,16 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
else
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
|
||||
/* Some relocs require a global offset table. FIXME: If this is
|
||||
a static link of PIC code, we need a global offset table but
|
||||
we don't really need to create the full dynamic linking
|
||||
information. */
|
||||
/* Some relocs require a global offset table. */
|
||||
if (dynobj == NULL)
|
||||
{
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_386_GOT32:
|
||||
case R_386_PLT32:
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOTPC:
|
||||
elf_hash_table (info)->dynobj = dynobj = abfd;
|
||||
if (! bfd_elf32_link_create_dynamic_sections (dynobj, info))
|
||||
if (! elf_i386_create_got_section (dynobj, info))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
@ -418,6 +435,12 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
if (sgot == NULL)
|
||||
{
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
BFD_ASSERT (sgot != NULL);
|
||||
}
|
||||
|
||||
if (srelgot == NULL
|
||||
&& (h != NULL || info->shared))
|
||||
{
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
|
||||
if (srelgot == NULL)
|
||||
{
|
||||
|
@ -432,7 +455,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||
return false;
|
||||
}
|
||||
BFD_ASSERT (sgot != NULL && srelgot != NULL);
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
|
@ -450,6 +472,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
}
|
||||
|
||||
srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -477,41 +501,32 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
break;
|
||||
}
|
||||
local_got_offsets[r_symndx] = sgot->_raw_size;
|
||||
|
||||
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;
|
||||
srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
||||
|
||||
break;
|
||||
|
||||
case R_386_PLT32:
|
||||
/* This symbol requires a procedure linkage table entry. */
|
||||
/* This symbol requires a procedure linkage table entry. We
|
||||
actually build the entry in adjust_dynamic_symbol,
|
||||
because this might be a case of linking PIC code without
|
||||
linking in any dynamic objects, in which case we don't
|
||||
need to generate a procedure linkage table after all. */
|
||||
|
||||
/* If this is a local symbol, we resolve it directly without
|
||||
creating a procedure linkage table entry. */
|
||||
if (h == NULL)
|
||||
continue;
|
||||
|
||||
if (h->plt_offset != (bfd_vma) -1)
|
||||
{
|
||||
/* There is already an entry for this symbol in the
|
||||
procedure linkage table. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (splt == NULL)
|
||||
{
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
|
||||
srelplt = bfd_get_section_by_name (dynobj, ".rel.plt");
|
||||
BFD_ASSERT (splt != NULL && sgotplt != NULL && srelplt != NULL);
|
||||
}
|
||||
|
||||
/* If this is the first .plt entry, make room for the
|
||||
special first entry. */
|
||||
if (splt->_raw_size == 0)
|
||||
splt->_raw_size += PLT_ENTRY_SIZE;
|
||||
|
||||
/* Make sure this symbol is output as a dynamic symbol. */
|
||||
if (h->dynindx == -1)
|
||||
{
|
||||
|
@ -519,15 +534,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||
return false;
|
||||
}
|
||||
|
||||
h->plt_offset = splt->_raw_size;
|
||||
|
||||
/* Make room for this entry. We need a procedure linkage
|
||||
table entry in .plt, a global offset table entry in
|
||||
.got.plt (which is placed in .got by the linker script),
|
||||
and a relocation in .rel.plt. */
|
||||
splt->_raw_size += PLT_ENTRY_SIZE;
|
||||
sgotplt->_raw_size += 4;
|
||||
srelplt->_raw_size += sizeof (Elf32_External_Rel);
|
||||
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
|
||||
|
||||
break;
|
||||
|
||||
|
@ -602,59 +609,66 @@ elf_i386_adjust_dynamic_symbol (info, h)
|
|||
|
||||
/* Make sure we know what is going on here. */
|
||||
BFD_ASSERT (dynobj != NULL
|
||||
&& (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_DEF_REGULAR) == 0
|
||||
&& h->root.type == bfd_link_hash_defined
|
||||
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
||||
== bfd_target_elf_flavour)
|
||||
&& (elf_elfheader (h->root.u.def.section->owner)->e_type
|
||||
== ET_DYN)
|
||||
&& h->root.u.def.section->output_section == NULL);
|
||||
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
|
||||
|| ((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_DEF_REGULAR) == 0
|
||||
&& (elf_elfheader (h->root.u.def.section->owner)->e_type
|
||||
== ET_DYN)
|
||||
&& h->root.u.def.section->output_section == NULL)));
|
||||
|
||||
/* If this is a function, put it in the procedure linkage table. We
|
||||
will fill in the contents of the procedure linkage table later,
|
||||
when we know the address of the .got section. */
|
||||
if (h->type == STT_FUNC)
|
||||
if (h->type == STT_FUNC
|
||||
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
|
||||
{
|
||||
if (! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
/* This case can occur if we saw a PLT32 reloc in an input
|
||||
file, but none of the input files were dynamic objects.
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
if (h->plt_offset != (bfd_vma) -1)
|
||||
{
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = h->plt_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this is the first .plt entry, make room for the
|
||||
special first entry. */
|
||||
if (s->_raw_size == 0)
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
/* If this is the first .plt entry, make room for the special
|
||||
first entry. */
|
||||
if (s->_raw_size == 0)
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
|
||||
/* Set the symbol to this location in the .plt. */
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = s->_raw_size;
|
||||
/* Set the symbol to this location in the .plt. */
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = s->_raw_size;
|
||||
|
||||
h->plt_offset = s->_raw_size;
|
||||
h->plt_offset = s->_raw_size;
|
||||
|
||||
/* Make room for this entry. */
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
/* Make room for this entry. */
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
|
||||
/* We also need to make an entry in the .got.plt section,
|
||||
which will be placed in the .got section by the linker
|
||||
script. */
|
||||
/* 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;
|
||||
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. */
|
||||
/* 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);
|
||||
}
|
||||
s = bfd_get_section_by_name (dynobj, ".rel.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size += sizeof (Elf32_External_Rel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -751,13 +765,27 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||
dynobj = elf_hash_table (info)->dynobj;
|
||||
BFD_ASSERT (dynobj != NULL);
|
||||
|
||||
/* Set the contents of the .interp section to the interpreter. */
|
||||
if (! info->shared)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
s = bfd_get_section_by_name (dynobj, ".interp");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
|
||||
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
|
||||
/* Set the contents of the .interp section to the interpreter. */
|
||||
if (! info->shared)
|
||||
{
|
||||
s = bfd_get_section_by_name (dynobj, ".interp");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
|
||||
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We may have created entries in the .rel.got section.
|
||||
However, if we are not creating the dynamic sections, we will
|
||||
not actually use these entries. Reset the size of .rel.got,
|
||||
which will cause it to get stripped from the output file
|
||||
below. */
|
||||
s = bfd_get_section_by_name (dynobj, ".rel.got");
|
||||
if (s != NULL)
|
||||
s->_raw_size = 0;
|
||||
}
|
||||
|
||||
/* The check_relocs and adjust_dynamic_symbol entry points have
|
||||
|
@ -859,39 +887,42 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add some entries to the .dynamic section. We fill in the values
|
||||
later, in elf_i386_finish_dynamic_sections, but we must add the
|
||||
entries now so that we get the correct size for the .dynamic
|
||||
section. The DT_DEBUG entry is filled in by the dynamic linker
|
||||
and used by the debugger. */
|
||||
if (! info->shared)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
||||
return false;
|
||||
}
|
||||
/* Add some entries to the .dynamic section. We fill in the
|
||||
values later, in elf_i386_finish_dynamic_sections, but we
|
||||
must add the entries now so that we get the correct size for
|
||||
the .dynamic section. The DT_DEBUG entry is filled in by the
|
||||
dynamic linker and used by the debugger. */
|
||||
if (! info->shared)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plt)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_REL)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
|
||||
return false;
|
||||
}
|
||||
if (plt)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_REL)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (relocs)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELENT,
|
||||
sizeof (Elf32_External_Rel)))
|
||||
return false;
|
||||
}
|
||||
if (relocs)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELENT,
|
||||
sizeof (Elf32_External_Rel)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reltext)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
||||
return false;
|
||||
if (reltext)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -910,7 +941,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
Elf_Internal_Rela *relocs;
|
||||
Elf_Internal_Sym *local_syms;
|
||||
asection **local_sections;
|
||||
char *output_names;
|
||||
{
|
||||
bfd *dynobj;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
|
@ -1026,8 +1056,33 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
|
||||
if (h != NULL)
|
||||
{
|
||||
BFD_ASSERT (h->got_offset != (bfd_vma) -1);
|
||||
relocation = sgot->output_offset + h->got_offset;
|
||||
bfd_vma off;
|
||||
|
||||
off = h->got_offset;
|
||||
BFD_ASSERT (off != (bfd_vma) -1);
|
||||
|
||||
if (! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
/* 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.
|
||||
|
||||
When doing a dynamic link, we create a .rel.got
|
||||
relocation entry to initialize the value. This
|
||||
is done in the finish_dynamic_symbol routine. */
|
||||
if ((off & 1) != 0)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, relocation,
|
||||
sgot->contents + off);
|
||||
h->got_offset |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
relocation = sgot->output_offset + off;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1045,23 +1100,26 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
off &= ~1;
|
||||
else
|
||||
{
|
||||
asection *srelgot;
|
||||
Elf_Internal_Rel outrel;
|
||||
|
||||
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
||||
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
|
||||
BFD_ASSERT (srelgot != NULL);
|
||||
if (info->shared)
|
||||
{
|
||||
asection *srelgot;
|
||||
Elf_Internal_Rel outrel;
|
||||
|
||||
outrel.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ off);
|
||||
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
||||
bfd_elf32_swap_reloc_out (output_bfd, &outrel,
|
||||
(((Elf32_External_Rel *)
|
||||
srelgot->contents)
|
||||
+ srelgot->reloc_count));
|
||||
++srelgot->reloc_count;
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
|
||||
BFD_ASSERT (srelgot != NULL);
|
||||
|
||||
outrel.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ off);
|
||||
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
||||
bfd_elf32_swap_reloc_out (output_bfd, &outrel,
|
||||
(((Elf32_External_Rel *)
|
||||
srelgot->contents)
|
||||
+ srelgot->reloc_count));
|
||||
++srelgot->reloc_count;
|
||||
}
|
||||
|
||||
local_got_offsets[r_symndx] |= 1;
|
||||
}
|
||||
|
@ -1112,13 +1170,19 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
if (h == NULL)
|
||||
break;
|
||||
|
||||
if (h->plt_offset == (bfd_vma) -1)
|
||||
{
|
||||
/* We didn't make a PLT entry for this symbol. This
|
||||
happens when statically linking PIC code. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (splt == NULL)
|
||||
{
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (splt != NULL);
|
||||
}
|
||||
|
||||
BFD_ASSERT (h != NULL && h->plt_offset != (bfd_vma) -1);
|
||||
relocation = (splt->output_section->vma
|
||||
+ splt->output_offset
|
||||
+ h->plt_offset);
|
||||
|
@ -1161,7 +1225,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
+ input_section->output_offset);
|
||||
if (r_type == R_386_PC32)
|
||||
{
|
||||
BFD_ASSERT (h != NULL && h->dynindx != (bfd_vma) -1);
|
||||
BFD_ASSERT (h != NULL && h->dynindx != -1);
|
||||
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
|
||||
}
|
||||
else
|
||||
|
@ -1395,111 +1459,120 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
|
|||
struct bfd_link_info *info;
|
||||
{
|
||||
bfd *dynobj;
|
||||
asection *splt;
|
||||
asection *sgot;
|
||||
asection *sdyn;
|
||||
Elf32_External_Dyn *dyncon, *dynconend;
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got.plt");
|
||||
BFD_ASSERT (sgot != NULL);
|
||||
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
||||
BFD_ASSERT (splt != NULL && sgot != NULL && sdyn != NULL);
|
||||
|
||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
||||
for (; dyncon < dynconend; dyncon++)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
Elf_Internal_Dyn dyn;
|
||||
const char *name;
|
||||
asection *s;
|
||||
asection *splt;
|
||||
Elf32_External_Dyn *dyncon, *dynconend;
|
||||
|
||||
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (splt != NULL && sdyn != NULL);
|
||||
|
||||
switch (dyn.d_tag)
|
||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
||||
for (; dyncon < dynconend; dyncon++)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
Elf_Internal_Dyn dyn;
|
||||
const char *name;
|
||||
asection *s;
|
||||
|
||||
case DT_PLTGOT:
|
||||
name = ".got";
|
||||
goto get_vma;
|
||||
case DT_JMPREL:
|
||||
name = ".rel.plt";
|
||||
get_vma:
|
||||
s = bfd_get_section_by_name (output_bfd, name);
|
||||
BFD_ASSERT (s != NULL);
|
||||
dyn.d_un.d_ptr = s->vma;
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
break;
|
||||
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
||||
|
||||
case DT_PLTRELSZ:
|
||||
s = bfd_get_section_by_name (output_bfd, ".rel.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
if (s->_cooked_size != 0)
|
||||
dyn.d_un.d_val = s->_cooked_size;
|
||||
else
|
||||
dyn.d_un.d_val = s->_raw_size;
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
break;
|
||||
|
||||
case DT_RELSZ:
|
||||
/* My reading of the SVR4 ABI indicates that the procedure
|
||||
linkage table relocs (DT_JMPREL) should be included in
|
||||
the overall relocs (DT_REL). This is what Solaris does.
|
||||
However, UnixWare can not handle that case. Therefore,
|
||||
we override the DT_RELSZ entry here to make it not
|
||||
include the JMPREL relocs. Since the linker script
|
||||
arranges for .rel.plt to follow all other relocation
|
||||
sections, we don't have to worry about changing the
|
||||
DT_REL entry. */
|
||||
s = bfd_get_section_by_name (output_bfd, ".rel.plt");
|
||||
if (s != NULL)
|
||||
switch (dyn.d_tag)
|
||||
{
|
||||
if (s->_cooked_size != 0)
|
||||
dyn.d_un.d_val -= s->_cooked_size;
|
||||
else
|
||||
dyn.d_un.d_val -= s->_raw_size;
|
||||
}
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
/* Fill in the first entry in the procedure linkage table. */
|
||||
if (splt->_raw_size > 0)
|
||||
{
|
||||
if (info->shared)
|
||||
memcpy (splt->contents, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
|
||||
else
|
||||
{
|
||||
memcpy (splt->contents, elf_i386_plt0_entry, PLT_ENTRY_SIZE);
|
||||
bfd_put_32 (output_bfd,
|
||||
sgot->output_section->vma + sgot->output_offset + 4,
|
||||
splt->contents + 2);
|
||||
bfd_put_32 (output_bfd,
|
||||
sgot->output_section->vma + sgot->output_offset + 8,
|
||||
splt->contents + 8);
|
||||
case DT_PLTGOT:
|
||||
name = ".got";
|
||||
goto get_vma;
|
||||
case DT_JMPREL:
|
||||
name = ".rel.plt";
|
||||
get_vma:
|
||||
s = bfd_get_section_by_name (output_bfd, name);
|
||||
BFD_ASSERT (s != NULL);
|
||||
dyn.d_un.d_ptr = s->vma;
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
break;
|
||||
|
||||
case DT_PLTRELSZ:
|
||||
s = bfd_get_section_by_name (output_bfd, ".rel.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
if (s->_cooked_size != 0)
|
||||
dyn.d_un.d_val = s->_cooked_size;
|
||||
else
|
||||
dyn.d_un.d_val = s->_raw_size;
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
break;
|
||||
|
||||
case DT_RELSZ:
|
||||
/* My reading of the SVR4 ABI indicates that the
|
||||
procedure linkage table relocs (DT_JMPREL) should be
|
||||
included in the overall relocs (DT_REL). This is
|
||||
what Solaris does. However, UnixWare can not handle
|
||||
that case. Therefore, we override the DT_RELSZ entry
|
||||
here to make it not include the JMPREL relocs. Since
|
||||
the linker script arranges for .rel.plt to follow all
|
||||
other relocation sections, we don't have to worry
|
||||
about changing the DT_REL entry. */
|
||||
s = bfd_get_section_by_name (output_bfd, ".rel.plt");
|
||||
if (s != NULL)
|
||||
{
|
||||
if (s->_cooked_size != 0)
|
||||
dyn.d_un.d_val -= s->_cooked_size;
|
||||
else
|
||||
dyn.d_un.d_val -= s->_raw_size;
|
||||
}
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in the first entry in the procedure linkage table. */
|
||||
if (splt->_raw_size > 0)
|
||||
{
|
||||
if (info->shared)
|
||||
memcpy (splt->contents, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
|
||||
else
|
||||
{
|
||||
memcpy (splt->contents, elf_i386_plt0_entry, PLT_ENTRY_SIZE);
|
||||
bfd_put_32 (output_bfd,
|
||||
sgot->output_section->vma + sgot->output_offset + 4,
|
||||
splt->contents + 2);
|
||||
bfd_put_32 (output_bfd,
|
||||
sgot->output_section->vma + sgot->output_offset + 8,
|
||||
splt->contents + 8);
|
||||
}
|
||||
}
|
||||
|
||||
/* UnixWare sets the entsize of .plt to 4, although that doesn't
|
||||
really seem like the right value. */
|
||||
elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
|
||||
}
|
||||
|
||||
/* Fill in the first three entries in the global offset table. */
|
||||
if (sgot->_raw_size > 0)
|
||||
{
|
||||
bfd_put_32 (output_bfd,
|
||||
sdyn->output_section->vma + sdyn->output_offset,
|
||||
sgot->contents);
|
||||
if (sdyn == NULL)
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
|
||||
else
|
||||
bfd_put_32 (output_bfd,
|
||||
sdyn->output_section->vma + sdyn->output_offset,
|
||||
sgot->contents);
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4);
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
|
||||
}
|
||||
|
||||
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
|
||||
|
||||
/* UnixWare sets the entsize of .plt to 4, although that doesn't
|
||||
really seem like the right value. */
|
||||
elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ static void elf_info_to_howto
|
|||
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
|
||||
static boolean elf32_sparc_create_dynamic_sections
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static boolean elf32_sparc_create_got_section
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static boolean elf32_sparc_check_relocs
|
||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||
const Elf_Internal_Rela *));
|
||||
|
@ -38,7 +40,7 @@ static boolean elf32_sparc_size_dynamic_sections
|
|||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static boolean elf32_sparc_relocate_section
|
||||
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
||||
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **, char *));
|
||||
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
|
||||
static boolean elf32_sparc_finish_dynamic_symbol
|
||||
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
|
||||
Elf_Internal_Sym *));
|
||||
|
@ -101,8 +103,8 @@ static reloc_howto_type elf_sparc_howto_table[] =
|
|||
HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_GOT13", false,0,0x00001fff,true),
|
||||
HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_GOT22", false,0,0x003fffff,true),
|
||||
HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_PC10", false,0,0x000003ff,true),
|
||||
HOWTO(R_SPARC_PC22, 0,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_PC22", false,0,0x003fffff,true),
|
||||
HOWTO(R_SPARC_WPLT30, 0,0,00,true, 0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_WPLT30", false,0,0x00000000,true),
|
||||
HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_PC22", false,0,0x003fffff,true),
|
||||
HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_WPLT30", false,0,0x3fffffff,true),
|
||||
HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_COPY", false,0,0x00000000,true),
|
||||
HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
|
||||
HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
|
||||
|
@ -232,18 +234,58 @@ elf32_sparc_create_dynamic_sections (abfd, info)
|
|||
&& ! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
|
||||
/* The first four entries in .plt are reserved. */
|
||||
s->_raw_size = 4 * PLT_ENTRY_SIZE;
|
||||
|
||||
s = bfd_make_section (abfd, ".rela.plt");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
|
||||
if (! elf32_sparc_create_got_section (abfd, info))
|
||||
return false;
|
||||
|
||||
/* The .dynbss section is a place to put symbols which are defined
|
||||
by dynamic objects, are referenced by regular objects, and are
|
||||
not functions. We must allocate space for them in the process
|
||||
image and use a R_SPARC_COPY reloc to tell the dynamic linker to
|
||||
initialize them at run time. The linker script puts the .dynbss
|
||||
section into the .bss section of the final image. */
|
||||
s = bfd_make_section (abfd, ".dynbss");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
|
||||
return false;
|
||||
|
||||
/* The .rela.bss section holds copy relocs. */
|
||||
if (! info->shared)
|
||||
{
|
||||
s = bfd_make_section (abfd, ".rela.bss");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Create the .got section to hold the global offset table. */
|
||||
|
||||
static boolean
|
||||
elf32_sparc_create_got_section (abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
register asection *s;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
/* This function may be called more than once. */
|
||||
if (bfd_get_section_by_name (abfd, ".got") != NULL)
|
||||
return true;
|
||||
|
||||
s = bfd_make_section (abfd, ".got");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags)
|
||||
|| ! bfd_set_section_flags (abfd, s,
|
||||
(SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY))
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
|
||||
|
@ -270,29 +312,8 @@ elf32_sparc_create_dynamic_sections (abfd, info)
|
|||
/* The first global offset table entry is reserved. */
|
||||
s->_raw_size += 4;
|
||||
|
||||
/* The .dynbss section is a place to put symbols which are defined
|
||||
by dynamic objects, are referenced by regular objects, and are
|
||||
not functions. We must allocate space for them in the process
|
||||
image and use a R_SPARC_COPY reloc to tell the dynamic linker to
|
||||
initialize them at run time. The linker script puts the .dynbss
|
||||
section into the .bss section of the final image. */
|
||||
s = bfd_make_section (abfd, ".dynbss");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
|
||||
return false;
|
||||
|
||||
/* The .rela.bss section holds copy relocs. */
|
||||
if (! info->shared)
|
||||
{
|
||||
s = bfd_make_section (abfd, ".rela.bss");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look through the relocs for a section during the first phase, and
|
||||
allocate space in the global offset table or procedure linkage
|
||||
|
@ -313,8 +334,6 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
const Elf_Internal_Rela *rel_end;
|
||||
asection *sgot;
|
||||
asection *srelgot;
|
||||
asection *splt;
|
||||
asection *srelplt;
|
||||
asection *sreloc;
|
||||
|
||||
if (info->relocateable)
|
||||
|
@ -327,8 +346,6 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
|
||||
sgot = NULL;
|
||||
srelgot = NULL;
|
||||
splt = NULL;
|
||||
srelplt = NULL;
|
||||
sreloc = NULL;
|
||||
|
||||
rel_end = relocs + sec->reloc_count;
|
||||
|
@ -343,27 +360,6 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
else
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
|
||||
/* Some relocs require a global offset table. FIXME: If this is
|
||||
a static link, we don't really need to create the full
|
||||
dynamic linking information. */
|
||||
if (dynobj == NULL)
|
||||
{
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_SPARC_GOT10:
|
||||
case R_SPARC_GOT13:
|
||||
case R_SPARC_GOT22:
|
||||
case R_SPARC_WPLT30:
|
||||
elf_hash_table (info)->dynobj = dynobj = abfd;
|
||||
if (! bfd_elf32_link_create_dynamic_sections (dynobj, info))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_SPARC_GOT10:
|
||||
|
@ -371,9 +367,23 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
case R_SPARC_GOT22:
|
||||
/* This symbol requires a global offset table entry. */
|
||||
|
||||
if (dynobj == NULL)
|
||||
{
|
||||
/* Create the .got section. */
|
||||
elf_hash_table (info)->dynobj = dynobj = abfd;
|
||||
if (! elf32_sparc_create_got_section (dynobj, info))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sgot == NULL)
|
||||
{
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
BFD_ASSERT (sgot != NULL);
|
||||
}
|
||||
|
||||
if (srelgot == NULL
|
||||
&& (h != NULL || info->shared))
|
||||
{
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
if (srelgot == NULL)
|
||||
{
|
||||
|
@ -384,10 +394,10 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
| SEC_LOAD
|
||||
| SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY
|
||||
| SEC_READONLY)))
|
||||
| SEC_READONLY))
|
||||
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||
return false;
|
||||
}
|
||||
BFD_ASSERT (sgot != NULL && srelgot != NULL);
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
|
@ -398,6 +408,15 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
break;
|
||||
}
|
||||
h->got_offset = sgot->_raw_size;
|
||||
|
||||
/* 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_Rela);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -425,15 +444,26 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
break;
|
||||
}
|
||||
local_got_offsets[r_symndx] = sgot->_raw_size;
|
||||
|
||||
if (info->shared)
|
||||
{
|
||||
/* If we are generating a shared object, we need to
|
||||
output a R_SPARC_RELATIVE reloc so that the
|
||||
dynamic linker can adjust this GOT entry. */
|
||||
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
||||
}
|
||||
}
|
||||
|
||||
sgot->_raw_size += 4;
|
||||
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
||||
|
||||
break;
|
||||
|
||||
case R_SPARC_WPLT30:
|
||||
/* This symbol requires a procedure linkage table entry. */
|
||||
/* This symbol requires a procedure linkage table entry. We
|
||||
actually build the entry in adjust_dynamic_symbol,
|
||||
because this might be a case of linking PIC code without
|
||||
linking in any dynamic objects, in which case we don't
|
||||
need to generate a procedure linkage table after all. */
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
|
@ -443,32 +473,14 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (h->plt_offset != (bfd_vma) -1)
|
||||
/* Make sure this symbol is output as a dynamic symbol. */
|
||||
if (h->dynindx == -1)
|
||||
{
|
||||
/* There is already an entry for this symbol in the
|
||||
procedure linkage table. */
|
||||
break;
|
||||
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (splt == NULL)
|
||||
{
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||
BFD_ASSERT (splt != NULL && srelplt != NULL);
|
||||
}
|
||||
|
||||
/* The procedure linkage table has a maximum size. */
|
||||
if (splt->_raw_size >= 0x400000)
|
||||
{
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
h->plt_offset = splt->_raw_size;
|
||||
|
||||
/* Make room for this entry. */
|
||||
splt->_raw_size += PLT_ENTRY_SIZE;
|
||||
srelplt->_raw_size += sizeof (Elf32_External_Rela);
|
||||
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
|
||||
|
||||
break;
|
||||
|
||||
|
@ -560,49 +572,66 @@ elf32_sparc_adjust_dynamic_symbol (info, h)
|
|||
|
||||
/* Make sure we know what is going on here. */
|
||||
BFD_ASSERT (dynobj != NULL
|
||||
&& (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_DEF_REGULAR) == 0
|
||||
&& h->root.type == bfd_link_hash_defined
|
||||
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
||||
== bfd_target_elf_flavour)
|
||||
&& (elf_elfheader (h->root.u.def.section->owner)->e_type
|
||||
== ET_DYN)
|
||||
&& h->root.u.def.section->output_section == NULL);
|
||||
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
|
||||
|| ((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_DEF_REGULAR) == 0
|
||||
&& (elf_elfheader (h->root.u.def.section->owner)->e_type
|
||||
== ET_DYN)
|
||||
&& h->root.u.def.section->output_section == NULL)));
|
||||
|
||||
/* If this is a function, put it in the procedure linkage table. We
|
||||
will fill in the contents of the procedure linkage table later
|
||||
(although we could actually do it here). */
|
||||
if (h->type == STT_FUNC)
|
||||
if (h->type == STT_FUNC
|
||||
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
|
||||
{
|
||||
if (h->plt_offset == (bfd_vma) -1)
|
||||
if (! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
/* The procedure linkage table has a maximum size. */
|
||||
if (s->_raw_size >= 0x400000)
|
||||
{
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the symbol to this location in the .plt. */
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = s->_raw_size;
|
||||
|
||||
h->plt_offset = s->_raw_size;
|
||||
|
||||
/* Make room for this entry. */
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
|
||||
/* We also need to make an entry in the .rela.plt section. */
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size += sizeof (Elf32_External_Rela);
|
||||
/* This case can occur if we saw a WPLT30 reloc in an input
|
||||
file, but none of the input files were dynamic objects.
|
||||
In such a case, we don't actually need to build a
|
||||
procedure linkage table, and we can just do a WDISP30
|
||||
reloc instead. */
|
||||
BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
/* The first four entries in .plt are reserved. */
|
||||
if (s->_raw_size == 0)
|
||||
s->_raw_size = 4 * PLT_ENTRY_SIZE;
|
||||
|
||||
/* The procedure linkage table has a maximum size. */
|
||||
if (s->_raw_size >= 0x400000)
|
||||
{
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the symbol to this location in the .plt. */
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = s->_raw_size;
|
||||
|
||||
h->plt_offset = s->_raw_size;
|
||||
|
||||
/* Make room for this entry. */
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
|
||||
/* We also need to make an entry in the .rela.plt section. */
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size += sizeof (Elf32_External_Rela);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -696,19 +725,34 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||
dynobj = elf_hash_table (info)->dynobj;
|
||||
BFD_ASSERT (dynobj != NULL);
|
||||
|
||||
/* Set the contents of the .interp section to the interpreter. */
|
||||
if (! info->shared)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
s = bfd_get_section_by_name (dynobj, ".interp");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
|
||||
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
|
||||
}
|
||||
/* Set the contents of the .interp section to the interpreter. */
|
||||
if (! info->shared)
|
||||
{
|
||||
s = bfd_get_section_by_name (dynobj, ".interp");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
|
||||
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
|
||||
}
|
||||
|
||||
/* Make space for the trailing nop in .plt. */
|
||||
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size += 4;
|
||||
/* Make space for the trailing nop in .plt. */
|
||||
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (s != NULL);
|
||||
if (s->_raw_size > 0)
|
||||
s->_raw_size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We may have created entries in the .rela.got section.
|
||||
However, if we are not creating the dynamic sections, we will
|
||||
not actually use these entries. Reset the size of .rela.got,
|
||||
which will cause it to get stripped from the output file
|
||||
below. */
|
||||
s = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
if (s != NULL)
|
||||
s->_raw_size = 0;
|
||||
}
|
||||
|
||||
/* The check_relocs and adjust_dynamic_symbol entry points have
|
||||
determined the sizes of the various dynamic sections. Allocate
|
||||
|
@ -717,6 +761,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||
for (s = dynobj->sections; s != NULL; s = s->next)
|
||||
{
|
||||
const char *name;
|
||||
boolean strip;
|
||||
|
||||
if ((s->flags & SEC_IN_MEMORY) == 0)
|
||||
continue;
|
||||
|
@ -725,21 +770,38 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||
of the dynobj section names depend upon the input files. */
|
||||
name = bfd_get_section_name (dynobj, s);
|
||||
|
||||
if (strncmp (name, ".rela", 5) == 0
|
||||
&& s->_raw_size > 0)
|
||||
strip = false;
|
||||
|
||||
if (strncmp (name, ".rela", 5) == 0)
|
||||
{
|
||||
asection *target;
|
||||
if (s->_raw_size == 0)
|
||||
{
|
||||
/* If we don't need this section, strip it from the
|
||||
output file. This is to handle .rela.bss and
|
||||
.rel.plt. We must create it in
|
||||
create_dynamic_sections, because it must be created
|
||||
before the linker maps input sections to output
|
||||
sections. The linker does that before
|
||||
adjust_dynamic_symbol is called, and it is that
|
||||
function which decides whether anything needs to go
|
||||
into these sections. */
|
||||
strip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
asection *target;
|
||||
|
||||
/* 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 + 5);
|
||||
if (target != NULL
|
||||
&& (target->flags & SEC_READONLY) != 0)
|
||||
reltext = 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 + 5);
|
||||
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. */
|
||||
s->reloc_count = 0;
|
||||
/* We use the reloc_count field as a counter if we need
|
||||
to copy relocs into the output file. */
|
||||
s->reloc_count = 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp (name, ".plt") != 0
|
||||
&& strcmp (name, ".got") != 0)
|
||||
|
@ -747,7 +809,21 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||
/* It's not one of our sections, so don't allocate space. */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (strip)
|
||||
{
|
||||
asection **spp;
|
||||
|
||||
for (spp = &s->output_section->owner->sections;
|
||||
*spp != s->output_section;
|
||||
spp = &(*spp)->next)
|
||||
;
|
||||
*spp = s->output_section->next;
|
||||
--s->output_section->owner->section_count;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Allocate memory for the section contents. */
|
||||
s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
|
||||
if (s->contents == NULL && s->_raw_size != 0)
|
||||
|
@ -757,31 +833,34 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add some entries to the .dynamic section. We fill in the values
|
||||
later, in elf32_sparc_finish_dynamic_sections, but we must add
|
||||
the entries now so that we get the correct size for the .dynamic
|
||||
section. The DT_DEBUG entry is filled in by the dynamic linker
|
||||
and used by the debugger. */
|
||||
if (! info->shared)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
||||
return false;
|
||||
}
|
||||
/* Add some entries to the .dynamic section. We fill in the
|
||||
values later, in elf32_sparc_finish_dynamic_sections, but we
|
||||
must add the entries now so that we get the correct size for
|
||||
the .dynamic section. The DT_DEBUG entry is filled in by the
|
||||
dynamic linker and used by the debugger. */
|
||||
if (! info->shared)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
|
||||
sizeof (Elf32_External_Rela)))
|
||||
return false;
|
||||
|
||||
if (reltext)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
|
||||
|| ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
|
||||
sizeof (Elf32_External_Rela)))
|
||||
return false;
|
||||
|
||||
if (reltext)
|
||||
{
|
||||
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -791,8 +870,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||
|
||||
static boolean
|
||||
elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
contents, relocs, local_syms, local_sections,
|
||||
output_names)
|
||||
contents, relocs, local_syms, local_sections)
|
||||
bfd *output_bfd;
|
||||
struct bfd_link_info *info;
|
||||
bfd *input_bfd;
|
||||
|
@ -801,7 +879,6 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
Elf_Internal_Rela *relocs;
|
||||
Elf_Internal_Sym *local_syms;
|
||||
asection **local_sections;
|
||||
char *output_names;
|
||||
{
|
||||
bfd *dynobj;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
|
@ -915,8 +992,33 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
|
||||
if (h != NULL)
|
||||
{
|
||||
BFD_ASSERT (h->got_offset != (bfd_vma) -1);
|
||||
relocation = sgot->output_offset + h->got_offset;
|
||||
bfd_vma off;
|
||||
|
||||
off = h->got_offset;
|
||||
BFD_ASSERT (off != (bfd_vma) -1);
|
||||
|
||||
if (! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
/* 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.
|
||||
|
||||
When doing a dynamic link, we create a .rela.got
|
||||
relocation entry to initialize the value. This
|
||||
is done in the finish_dynamic_symbol routine. */
|
||||
if ((off & 1) != 0)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, relocation,
|
||||
sgot->contents + off);
|
||||
h->got_offset |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
relocation = sgot->output_offset + off;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -928,30 +1030,35 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
off = local_got_offsets[r_symndx];
|
||||
|
||||
/* The offset must always be a multiple of 4. We use
|
||||
the least significant bit to record whether we have
|
||||
already generated the necessary reloc. */
|
||||
the least significant bit to record whether we have
|
||||
already processed this entry. */
|
||||
if ((off & 1) != 0)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
asection *srelgot;
|
||||
Elf_Internal_Rela outrel;
|
||||
|
||||
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
||||
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
BFD_ASSERT (srelgot != NULL);
|
||||
if (info->shared)
|
||||
{
|
||||
asection *srelgot;
|
||||
Elf_Internal_Rela outrel;
|
||||
|
||||
outrel.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ off);
|
||||
outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
|
||||
outrel.r_addend = 0;
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
|
||||
(((Elf32_External_Rela *)
|
||||
srelgot->contents)
|
||||
+ srelgot->reloc_count));
|
||||
++srelgot->reloc_count;
|
||||
/* We need to generate a R_SPARC_RELATIVE reloc
|
||||
for the dynamic linker. */
|
||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||
BFD_ASSERT (srelgot != NULL);
|
||||
|
||||
outrel.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ off);
|
||||
outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
|
||||
outrel.r_addend = 0;
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
|
||||
(((Elf32_External_Rela *)
|
||||
srelgot->contents)
|
||||
+ srelgot->reloc_count));
|
||||
++srelgot->reloc_count;
|
||||
}
|
||||
|
||||
local_got_offsets[r_symndx] |= 1;
|
||||
}
|
||||
|
@ -964,13 +1071,21 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
case R_SPARC_WPLT30:
|
||||
/* Relocation is to the entry for this symbol in the
|
||||
procedure linkage table. */
|
||||
BFD_ASSERT (h != NULL);
|
||||
|
||||
if (h->plt_offset == (bfd_vma) -1)
|
||||
{
|
||||
/* We didn't make a PLT entry for this symbol. This
|
||||
happens when statically linking PIC code. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (splt == NULL)
|
||||
{
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (splt != NULL);
|
||||
}
|
||||
|
||||
BFD_ASSERT (h != NULL && h->plt_offset != (bfd_vma) -1);
|
||||
relocation = (splt->output_section->vma
|
||||
+ splt->output_offset
|
||||
+ h->plt_offset);
|
||||
|
@ -1029,7 +1144,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
+ input_section->output_offset);
|
||||
if (h != NULL)
|
||||
{
|
||||
BFD_ASSERT (h->dynindx != (bfd_vma) -1);
|
||||
BFD_ASSERT (h->dynindx != -1);
|
||||
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
|
||||
outrel.r_addend = 0;
|
||||
}
|
||||
|
@ -1098,7 +1213,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
name = h->root.root.string;
|
||||
else
|
||||
{
|
||||
name = output_names + sym->st_name;
|
||||
name = elf_string_from_elf_section (input_bfd,
|
||||
symtab_hdr->sh_link,
|
||||
sym->st_name);
|
||||
if (name == NULL)
|
||||
return false;
|
||||
if (*name == '\0')
|
||||
|
@ -1244,74 +1361,86 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
|
|||
struct bfd_link_info *info;
|
||||
{
|
||||
bfd *dynobj;
|
||||
asection *splt;
|
||||
asection *sgot;
|
||||
asection *sdyn;
|
||||
Elf32_External_Dyn *dyncon, *dynconend;
|
||||
asection *sgot;
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
||||
BFD_ASSERT (splt != NULL && sgot != NULL && sdyn != NULL);
|
||||
|
||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
||||
for (; dyncon < dynconend; dyncon++)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
Elf_Internal_Dyn dyn;
|
||||
const char *name;
|
||||
boolean size;
|
||||
asection *splt;
|
||||
Elf32_External_Dyn *dyncon, *dynconend;
|
||||
|
||||
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
BFD_ASSERT (splt != NULL && sdyn != NULL);
|
||||
|
||||
switch (dyn.d_tag)
|
||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
||||
for (; dyncon < dynconend; dyncon++)
|
||||
{
|
||||
case DT_PLTGOT: name = ".plt"; size = false; break;
|
||||
case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
|
||||
case DT_JMPREL: name = ".rela.plt"; size = false; break;
|
||||
default: name = NULL; size = false; break;
|
||||
}
|
||||
Elf_Internal_Dyn dyn;
|
||||
const char *name;
|
||||
boolean size;
|
||||
|
||||
if (name != NULL)
|
||||
{
|
||||
asection *s;
|
||||
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
|
||||
|
||||
s = bfd_get_section_by_name (output_bfd, name);
|
||||
BFD_ASSERT (s != NULL);
|
||||
if (! size)
|
||||
dyn.d_un.d_ptr = s->vma;
|
||||
else
|
||||
switch (dyn.d_tag)
|
||||
{
|
||||
if (s->_cooked_size != 0)
|
||||
dyn.d_un.d_val = s->_cooked_size;
|
||||
else
|
||||
dyn.d_un.d_val = s->_raw_size;
|
||||
case DT_PLTGOT: name = ".plt"; size = false; break;
|
||||
case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
|
||||
case DT_JMPREL: name = ".rela.plt"; size = false; break;
|
||||
default: name = NULL; size = false; break;
|
||||
}
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the first four entries in the procedure linkage table, and
|
||||
put a nop in the last four bytes. */
|
||||
if (splt->_raw_size > 0)
|
||||
{
|
||||
memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
|
||||
bfd_put_32 (output_bfd, SPARC_NOP,
|
||||
splt->contents + splt->_raw_size - 4);
|
||||
if (name != NULL)
|
||||
{
|
||||
asection *s;
|
||||
|
||||
s = bfd_get_section_by_name (output_bfd, name);
|
||||
BFD_ASSERT (s != NULL);
|
||||
if (! size)
|
||||
dyn.d_un.d_ptr = s->vma;
|
||||
else
|
||||
{
|
||||
if (s->_cooked_size != 0)
|
||||
dyn.d_un.d_val = s->_cooked_size;
|
||||
else
|
||||
dyn.d_un.d_val = s->_raw_size;
|
||||
}
|
||||
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the first four entries in the procedure linkage table,
|
||||
and put a nop in the last four bytes. */
|
||||
if (splt->_raw_size > 0)
|
||||
{
|
||||
memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
|
||||
bfd_put_32 (output_bfd, SPARC_NOP,
|
||||
splt->contents + splt->_raw_size - 4);
|
||||
}
|
||||
|
||||
elf_section_data (splt->output_section)->this_hdr.sh_entsize =
|
||||
PLT_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* Set the first entry in the global offset table to the address of
|
||||
the dynamic section. */
|
||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||
BFD_ASSERT (sgot != NULL);
|
||||
if (sgot->_raw_size > 0)
|
||||
bfd_put_32 (output_bfd,
|
||||
sdyn->output_section->vma + sdyn->output_offset,
|
||||
sgot->contents);
|
||||
{
|
||||
if (sdyn == NULL)
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
|
||||
else
|
||||
bfd_put_32 (output_bfd,
|
||||
sdyn->output_section->vma + sdyn->output_offset,
|
||||
sgot->contents);
|
||||
}
|
||||
|
||||
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
|
||||
elf_section_data (splt->output_section)->this_hdr.sh_entsize =
|
||||
PLT_ENTRY_SIZE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
318
bfd/elfcode.h
318
bfd/elfcode.h
|
@ -3868,21 +3868,36 @@ elf_link_add_archive_symbols (abfd, info)
|
|||
|
||||
/* Record a new dynamic symbol. We record the dynamic symbols as we
|
||||
read the input files, since we need to have a list of all of them
|
||||
before we can determine the final sizes of the output sections. */
|
||||
before we can determine the final sizes of the output sections.
|
||||
Note that we may actually call this function even though we are not
|
||||
going to output any dynamic symbols; in some cases we know that a
|
||||
symbol should be in the dynamic symbol table, but only if there is
|
||||
one. */
|
||||
|
||||
INLINE boolean
|
||||
boolean
|
||||
elf_link_record_dynamic_symbol (info, h)
|
||||
struct bfd_link_info *info;
|
||||
struct elf_link_hash_entry *h;
|
||||
{
|
||||
if (h->dynindx == -1)
|
||||
{
|
||||
struct bfd_strtab_hash *dynstr;
|
||||
|
||||
h->dynindx = elf_hash_table (info)->dynsymcount;
|
||||
++elf_hash_table (info)->dynsymcount;
|
||||
h->dynstr_index =
|
||||
(unsigned long) _bfd_stringtab_add (elf_hash_table (info)->dynstr,
|
||||
h->root.root.string,
|
||||
true, false);
|
||||
|
||||
dynstr = elf_hash_table (info)->dynstr;
|
||||
if (dynstr == NULL)
|
||||
{
|
||||
/* Create a strtab to hold the dynamic symbol names. */
|
||||
elf_hash_table (info)->dynstr = dynstr = elf_stringtab_init ();
|
||||
if (dynstr == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
h->dynstr_index = ((unsigned long)
|
||||
_bfd_stringtab_add (dynstr, h->root.root.string,
|
||||
true, false));
|
||||
if (h->dynstr_index == (unsigned long) -1)
|
||||
return false;
|
||||
}
|
||||
|
@ -3975,12 +3990,11 @@ elf_link_add_object_symbols (abfd, info)
|
|||
format. FIXME: If there are no input BFD's of the same
|
||||
format as the output, we can't make a shared library. */
|
||||
if (info->shared
|
||||
&& elf_hash_table (info)->dynobj == NULL
|
||||
&& ! elf_hash_table (info)->dynamic_sections_created
|
||||
&& abfd->xvec == info->hash->creator)
|
||||
{
|
||||
if (! elf_link_create_dynamic_sections (abfd, info))
|
||||
goto error_return;
|
||||
elf_hash_table (info)->dynobj = abfd;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -4065,14 +4079,11 @@ elf_link_add_object_symbols (abfd, info)
|
|||
abfd->sections = NULL;
|
||||
|
||||
/* If this is the first dynamic object found in the link, create
|
||||
the special sections required for dynamic linking. We need
|
||||
to put them somewhere, and attaching them to the first
|
||||
dynamic object is as good place as any. */
|
||||
if (elf_hash_table (info)->dynobj == NULL)
|
||||
the special sections required for dynamic linking. */
|
||||
if (! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
if (! elf_link_create_dynamic_sections (abfd, info))
|
||||
goto error_return;
|
||||
elf_hash_table (info)->dynobj = abfd;
|
||||
}
|
||||
|
||||
/* Add a DT_NEEDED entry for this dynamic object. */
|
||||
|
@ -4464,11 +4475,11 @@ elf_link_add_object_symbols (abfd, info)
|
|||
}
|
||||
|
||||
/* Create some sections which will be filled in with dynamic linking
|
||||
information. The ABFD argument is an input file which is a dynamic
|
||||
object. The dynamic sections take up virtual memory space when the
|
||||
final executable is run, so we need to create them before addresses
|
||||
are assigned to the output sections. We work out the actual
|
||||
contents and size of these sections later. */
|
||||
information. ABFD is an input file which requires dynamic sections
|
||||
to be created. The dynamic sections take up virtual memory space
|
||||
when the final executable is run, so we need to create them before
|
||||
addresses are assigned to the output sections. We work out the
|
||||
actual contents and size of these sections later. */
|
||||
|
||||
boolean
|
||||
elf_link_create_dynamic_sections (abfd, info)
|
||||
|
@ -4480,6 +4491,15 @@ elf_link_create_dynamic_sections (abfd, info)
|
|||
struct elf_link_hash_entry *h;
|
||||
struct elf_backend_data *bed;
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
return true;
|
||||
|
||||
/* Make sure that all dynamic sections use the same input BFD. */
|
||||
if (elf_hash_table (info)->dynobj == NULL)
|
||||
elf_hash_table (info)->dynobj = abfd;
|
||||
else
|
||||
abfd = elf_hash_table (info)->dynobj;
|
||||
|
||||
/* Note that we set the SEC_IN_MEMORY flag for all of these
|
||||
sections. */
|
||||
flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
|
||||
|
@ -4500,18 +4520,18 @@ elf_link_create_dynamic_sections (abfd, info)
|
|||
|| ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
|
||||
return false;
|
||||
|
||||
/* The first .dynsym symbol is a dummy. */
|
||||
elf_hash_table (info)->dynsymcount = 1;
|
||||
|
||||
s = bfd_make_section (abfd, ".dynstr");
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
|
||||
return false;
|
||||
|
||||
/* Create a strtab to hold the dynamic symbol names. */
|
||||
elf_hash_table (info)->dynstr = elf_stringtab_init ();
|
||||
if (elf_hash_table (info)->dynstr == NULL)
|
||||
return false;
|
||||
{
|
||||
elf_hash_table (info)->dynstr = elf_stringtab_init ();
|
||||
if (elf_hash_table (info)->dynstr == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
s = bfd_make_section (abfd, ".dynamic");
|
||||
if (s == NULL
|
||||
|
@ -4550,7 +4570,12 @@ elf_link_create_dynamic_sections (abfd, info)
|
|||
backend set the right flags. The backend will normally create
|
||||
the .got and .plt sections. */
|
||||
bed = get_elf_backend_data (abfd);
|
||||
return (*bed->elf_backend_create_dynamic_sections) (abfd, info);
|
||||
if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
|
||||
return false;
|
||||
|
||||
elf_hash_table (info)->dynamic_sections_created = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add an entry to the .dynamic table. */
|
||||
|
@ -4777,7 +4802,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|
|||
asection **sinterpptr;
|
||||
{
|
||||
bfd *dynobj;
|
||||
size_t dynsymcount;
|
||||
asection *s;
|
||||
Elf_Internal_Sym isym;
|
||||
size_t i;
|
||||
|
@ -4787,127 +4811,138 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|
|||
*sinterpptr = NULL;
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
dynsymcount = elf_hash_table (info)->dynsymcount;
|
||||
|
||||
/* If there were no dynamic objects in the link, there is nothing to
|
||||
do here. */
|
||||
if (dynobj == NULL)
|
||||
return true;
|
||||
|
||||
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
|
||||
BFD_ASSERT (*sinterpptr != NULL || info->shared);
|
||||
|
||||
/* Set the size of the .dynsym and .hash sections. We counted the
|
||||
number of dynamic symbols in elf_link_add_object_symbols. We
|
||||
will build the contents of .dynsym and .hash when we build the
|
||||
final symbol table, because until then we do not know the correct
|
||||
value to give the symbols. We built the .dynstr section as we
|
||||
went along in elf_link_add_object_symbols. */
|
||||
s = bfd_get_section_by_name (dynobj, ".dynsym");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
|
||||
s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
|
||||
if (s->contents == NULL && s->_raw_size != 0)
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
size_t dynsymcount;
|
||||
bfd_size_type strsize;
|
||||
|
||||
/* The first entry in .dynsym is a dummy symbol. */
|
||||
isym.st_value = 0;
|
||||
isym.st_size = 0;
|
||||
isym.st_name = 0;
|
||||
isym.st_info = 0;
|
||||
isym.st_other = 0;
|
||||
isym.st_shndx = 0;
|
||||
elf_swap_symbol_out (output_bfd, &isym,
|
||||
(Elf_External_Sym *) s->contents);
|
||||
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
|
||||
BFD_ASSERT (*sinterpptr != NULL || info->shared);
|
||||
|
||||
for (i = 0; elf_buckets[i] != 0; i++)
|
||||
{
|
||||
bucketcount = elf_buckets[i];
|
||||
if (dynsymcount < elf_buckets[i + 1])
|
||||
break;
|
||||
}
|
||||
/* Set the size of the .dynsym and .hash sections. We counted
|
||||
the number of dynamic symbols in elf_link_add_object_symbols.
|
||||
We will build the contents of .dynsym and .hash when we build
|
||||
the final symbol table, because until then we do not know the
|
||||
correct value to give the symbols. We built the .dynstr
|
||||
section as we went along in elf_link_add_object_symbols. */
|
||||
dynsymcount = elf_hash_table (info)->dynsymcount;
|
||||
s = bfd_get_section_by_name (dynobj, ".dynsym");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
|
||||
s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
|
||||
if (s->contents == NULL && s->_raw_size != 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".hash");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
|
||||
s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
|
||||
if (s->contents == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
memset (s->contents, 0, s->_raw_size);
|
||||
/* The first entry in .dynsym is a dummy symbol. */
|
||||
isym.st_value = 0;
|
||||
isym.st_size = 0;
|
||||
isym.st_name = 0;
|
||||
isym.st_info = 0;
|
||||
isym.st_other = 0;
|
||||
isym.st_shndx = 0;
|
||||
elf_swap_symbol_out (output_bfd, &isym,
|
||||
(Elf_External_Sym *) s->contents);
|
||||
|
||||
put_word (output_bfd, bucketcount, s->contents);
|
||||
put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
|
||||
for (i = 0; elf_buckets[i] != 0; i++)
|
||||
{
|
||||
bucketcount = elf_buckets[i];
|
||||
if (dynsymcount < elf_buckets[i + 1])
|
||||
break;
|
||||
}
|
||||
|
||||
elf_hash_table (info)->bucketcount = bucketcount;
|
||||
s = bfd_get_section_by_name (dynobj, ".hash");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
|
||||
s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
|
||||
if (s->contents == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
memset (s->contents, 0, s->_raw_size);
|
||||
|
||||
if (soname != NULL)
|
||||
{
|
||||
bfd_size_type indx;
|
||||
put_word (output_bfd, bucketcount, s->contents);
|
||||
put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
|
||||
|
||||
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, soname,
|
||||
true, true);
|
||||
if (indx == (bfd_size_type) -1
|
||||
|| ! elf_add_dynamic_entry (info, DT_SONAME, indx))
|
||||
return false;
|
||||
}
|
||||
elf_hash_table (info)->bucketcount = bucketcount;
|
||||
|
||||
if (rpath != NULL)
|
||||
{
|
||||
bfd_size_type indx;
|
||||
if (soname != NULL)
|
||||
{
|
||||
bfd_size_type indx;
|
||||
|
||||
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
|
||||
true, true);
|
||||
if (indx == (bfd_size_type) -1
|
||||
|| ! elf_add_dynamic_entry (info, DT_RPATH, indx))
|
||||
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, soname,
|
||||
true, true);
|
||||
if (indx == (bfd_size_type) -1
|
||||
|| ! elf_add_dynamic_entry (info, DT_SONAME, indx))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpath != NULL)
|
||||
{
|
||||
bfd_size_type indx;
|
||||
|
||||
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
|
||||
true, true);
|
||||
if (indx == (bfd_size_type) -1
|
||||
|| ! elf_add_dynamic_entry (info, DT_RPATH, indx))
|
||||
return false;
|
||||
}
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".dynstr");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
|
||||
|
||||
/* Find all symbols which were defined in a dynamic object and make
|
||||
the backend pick a reasonable value for them. */
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_adjust_dynamic_symbol,
|
||||
(PTR) info);
|
||||
|
||||
/* Add some entries to the .dynamic section. We fill in some of the
|
||||
values later, in elf_bfd_final_link, but we must add the entries
|
||||
now so that we know the final size of the .dynamic section. */
|
||||
if (bfd_get_section_by_name (output_bfd, ".init") != NULL)
|
||||
{
|
||||
if (! elf_add_dynamic_entry (info, DT_INIT, 0))
|
||||
return false;
|
||||
}
|
||||
if (bfd_get_section_by_name (output_bfd, ".fini") != NULL)
|
||||
{
|
||||
if (! elf_add_dynamic_entry (info, DT_FINI, 0))
|
||||
return false;
|
||||
}
|
||||
strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
|
||||
if (! elf_add_dynamic_entry (info, DT_HASH, 0)
|
||||
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|
||||
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|
||||
|| ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
|
||||
|| ! elf_add_dynamic_entry (info, DT_SYMENT,
|
||||
sizeof (Elf_External_Sym)))
|
||||
return false;
|
||||
}
|
||||
|
||||
s = bfd_get_section_by_name (dynobj, ".dynstr");
|
||||
BFD_ASSERT (s != NULL);
|
||||
s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
|
||||
|
||||
/* Find all symbols which were defined in a dynamic object and make
|
||||
the backend pick a reasonable value for them. */
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_adjust_dynamic_symbol,
|
||||
(PTR) info);
|
||||
|
||||
/* Add some entries to the .dynamic section. We fill in some of the
|
||||
values later, in elf_bfd_final_link, but we must add the entries
|
||||
now so that we know the final size of the .dynamic section. */
|
||||
if (bfd_get_section_by_name (output_bfd, ".init") != NULL)
|
||||
{
|
||||
if (! elf_add_dynamic_entry (info, DT_INIT, 0))
|
||||
return false;
|
||||
}
|
||||
if (bfd_get_section_by_name (output_bfd, ".fini") != NULL)
|
||||
{
|
||||
if (! elf_add_dynamic_entry (info, DT_FINI, 0))
|
||||
return false;
|
||||
}
|
||||
if (! elf_add_dynamic_entry (info, DT_HASH, 0)
|
||||
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|
||||
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|
||||
|| ! elf_add_dynamic_entry (info, DT_STRSZ,
|
||||
_bfd_stringtab_size (elf_hash_table (info)
|
||||
->dynstr))
|
||||
|| ! elf_add_dynamic_entry (info, DT_SYMENT,
|
||||
sizeof (Elf_External_Sym)))
|
||||
return false;
|
||||
|
||||
/* The backend must work out the sizes of all the other dynamic
|
||||
sections. */
|
||||
bed = get_elf_backend_data (output_bfd);
|
||||
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
|
||||
return false;
|
||||
|
||||
return elf_add_dynamic_entry (info, DT_NULL, 0);
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
if (! elf_add_dynamic_entry (info, DT_NULL, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Make the backend pick a good value for a dynamic symbol. This is
|
||||
|
@ -4923,13 +4958,15 @@ elf_adjust_dynamic_symbol (h, data)
|
|||
bfd *dynobj;
|
||||
struct elf_backend_data *bed;
|
||||
|
||||
/* If this symbol 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? */
|
||||
if ((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)
|
||||
/* 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? */
|
||||
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))
|
||||
return true;
|
||||
|
||||
/* If we've already adjusted this symbol, don't do it again. This
|
||||
|
@ -5069,6 +5106,7 @@ elf_bfd_final_link (abfd, info)
|
|||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
boolean dynamic;
|
||||
bfd *dynobj;
|
||||
struct elf_final_link_info finfo;
|
||||
register asection *o;
|
||||
|
@ -5088,6 +5126,7 @@ elf_bfd_final_link (abfd, info)
|
|||
if (info->shared)
|
||||
abfd->flags |= DYNAMIC;
|
||||
|
||||
dynamic = elf_hash_table (info)->dynamic_sections_created;
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
|
||||
finfo.info = info;
|
||||
|
@ -5095,7 +5134,7 @@ elf_bfd_final_link (abfd, info)
|
|||
finfo.symstrtab = elf_stringtab_init ();
|
||||
if (finfo.symstrtab == NULL)
|
||||
return false;
|
||||
if (dynobj == NULL)
|
||||
if (! dynamic)
|
||||
{
|
||||
finfo.dynsym_sec = NULL;
|
||||
finfo.hash_sec = NULL;
|
||||
|
@ -5415,7 +5454,7 @@ elf_bfd_final_link (abfd, info)
|
|||
/* The sh_info field records the index of the first non local
|
||||
symbol. */
|
||||
symtab_hdr->sh_info = abfd->symcount;
|
||||
if (dynobj != NULL)
|
||||
if (dynamic)
|
||||
elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
|
||||
|
||||
/* We get the global symbols from the hash table. */
|
||||
|
@ -5500,9 +5539,9 @@ elf_bfd_final_link (abfd, info)
|
|||
o->reloc_count = 0;
|
||||
}
|
||||
|
||||
/* If we are linking against a dynamic object, finish up the dynamic
|
||||
linking information. */
|
||||
if (dynobj != NULL)
|
||||
/* If we are linking against a dynamic object, or generating a
|
||||
shared library, finish up the dynamic linking information. */
|
||||
if (dynamic)
|
||||
{
|
||||
Elf_External_Dyn *dyncon, *dynconend;
|
||||
|
||||
|
@ -5577,13 +5616,18 @@ elf_bfd_final_link (abfd, info)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have created any dynamic sections, then output them. */
|
||||
if (dynobj != NULL)
|
||||
{
|
||||
if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
|
||||
goto error_return;
|
||||
|
||||
for (o = dynobj->sections; o != NULL; o = o->next)
|
||||
{
|
||||
if ((o->flags & SEC_HAS_CONTENTS) == 0)
|
||||
if ((o->flags & SEC_HAS_CONTENTS) == 0
|
||||
|| o->_raw_size == 0)
|
||||
continue;
|
||||
if ((o->flags & SEC_IN_MEMORY) == 0)
|
||||
{
|
||||
|
@ -5859,7 +5903,8 @@ elf_link_output_extsym (h, data)
|
|||
/* If this symbol should be put in the .dynsym section, then put it
|
||||
there now. We have already know the symbol index. We also fill
|
||||
in the entry in the .hash section. */
|
||||
if (h->dynindx != -1)
|
||||
if (h->dynindx != -1
|
||||
&& elf_hash_table (finfo->info)->dynamic_sections_created)
|
||||
{
|
||||
struct elf_backend_data *bed;
|
||||
size_t bucketcount;
|
||||
|
@ -5885,7 +5930,8 @@ elf_link_output_extsym (h, data)
|
|||
+ h->dynindx));
|
||||
|
||||
bucketcount = elf_hash_table (finfo->info)->bucketcount;
|
||||
bucket = bfd_elf_hash ((const unsigned char *) h->root.root.string) % bucketcount;
|
||||
bucket = (bfd_elf_hash ((const unsigned char *) h->root.root.string)
|
||||
% bucketcount);
|
||||
bucketpos = ((bfd_byte *) finfo->hash_sec->contents
|
||||
+ (bucket + 2) * (ARCH_SIZE / 8));
|
||||
chain = get_word (finfo->output_bfd, bucketpos);
|
||||
|
|
11
bfd/libelf.h
11
bfd/libelf.h
|
@ -121,6 +121,8 @@ struct elf_link_hash_entry
|
|||
#define ELF_LINK_HASH_DEFINED_WEAK 040
|
||||
/* Symbol needs a copy reloc. */
|
||||
#define ELF_LINK_HASH_NEEDS_COPY 0100
|
||||
/* Symbol needs a procedure linkage table entry. */
|
||||
#define ELF_LINK_HASH_NEEDS_PLT 0200
|
||||
};
|
||||
|
||||
/* ELF linker hash table. */
|
||||
|
@ -128,9 +130,12 @@ struct elf_link_hash_entry
|
|||
struct elf_link_hash_table
|
||||
{
|
||||
struct bfd_link_hash_table root;
|
||||
/* The first dynamic object found during a link. We create several
|
||||
special input sections when linking against dynamic objects, and
|
||||
we simply attach them to the first one found. */
|
||||
/* Whether we have created the special dynamic sections required
|
||||
when linking against or generating a shared object. */
|
||||
boolean dynamic_sections_created;
|
||||
/* The BFD used to hold special sections created by the linker.
|
||||
This will be the first BFD found which requires these sections to
|
||||
be created. */
|
||||
bfd *dynobj;
|
||||
/* The number of symbols found in the link which must be put into
|
||||
the .dynsym section. */
|
||||
|
|
Loading…
Reference in a new issue