mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-07-01 18:32:32 +08:00
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:
@ -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)
|
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
|
* elfcode.h (elf_map_symbols): Don't worry about section symbols
|
||||||
|
317
bfd/elf32-i386.c
317
bfd/elf32-i386.c
@ -31,6 +31,8 @@ static void elf_i386_info_to_howto_rel
|
|||||||
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
|
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
|
||||||
static boolean elf_i386_create_dynamic_sections
|
static boolean elf_i386_create_dynamic_sections
|
||||||
PARAMS ((bfd *, struct bfd_link_info *));
|
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
|
static boolean elf_i386_check_relocs
|
||||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||||
const Elf_Internal_Rela *));
|
const Elf_Internal_Rela *));
|
||||||
@ -269,39 +271,9 @@ elf_i386_create_dynamic_sections (abfd, info)
|
|||||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
s = bfd_make_section (abfd, ".got");
|
if (! elf_i386_create_got_section (abfd, info))
|
||||||
if (s == NULL
|
|
||||||
|| ! bfd_set_section_flags (abfd, s, flags)
|
|
||||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
|
||||||
return false;
|
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
|
/* The .dynbss section is a place to put symbols which are defined
|
||||||
by dynamic objects, are referenced by regular objects, and are
|
by dynamic objects, are referenced by regular objects, and are
|
||||||
not functions. We must allocate space for them in the process
|
not functions. We must allocate space for them in the process
|
||||||
@ -336,6 +308,61 @@ elf_i386_create_dynamic_sections (abfd, info)
|
|||||||
return true;
|
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
|
/* Look through the relocs for a section during the first phase, and
|
||||||
allocate space in the global offset table or procedure linkage
|
allocate space in the global offset table or procedure linkage
|
||||||
table. */
|
table. */
|
||||||
@ -355,9 +382,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
const Elf_Internal_Rela *rel_end;
|
const Elf_Internal_Rela *rel_end;
|
||||||
asection *sgot;
|
asection *sgot;
|
||||||
asection *srelgot;
|
asection *srelgot;
|
||||||
asection *splt;
|
|
||||||
asection *sgotplt;
|
|
||||||
asection *srelplt;
|
|
||||||
asection *sreloc;
|
asection *sreloc;
|
||||||
|
|
||||||
if (info->relocateable)
|
if (info->relocateable)
|
||||||
@ -370,9 +394,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
|
|
||||||
sgot = NULL;
|
sgot = NULL;
|
||||||
srelgot = NULL;
|
srelgot = NULL;
|
||||||
splt = NULL;
|
|
||||||
sgotplt = NULL;
|
|
||||||
srelplt = NULL;
|
|
||||||
sreloc = NULL;
|
sreloc = NULL;
|
||||||
|
|
||||||
rel_end = relocs + sec->reloc_count;
|
rel_end = relocs + sec->reloc_count;
|
||||||
@ -388,20 +409,16 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
else
|
else
|
||||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
|
|
||||||
/* Some relocs require a global offset table. FIXME: If this is
|
/* Some relocs require a global offset table. */
|
||||||
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. */
|
|
||||||
if (dynobj == NULL)
|
if (dynobj == NULL)
|
||||||
{
|
{
|
||||||
switch (ELF32_R_TYPE (rel->r_info))
|
switch (ELF32_R_TYPE (rel->r_info))
|
||||||
{
|
{
|
||||||
case R_386_GOT32:
|
case R_386_GOT32:
|
||||||
case R_386_PLT32:
|
|
||||||
case R_386_GOTOFF:
|
case R_386_GOTOFF:
|
||||||
case R_386_GOTPC:
|
case R_386_GOTPC:
|
||||||
elf_hash_table (info)->dynobj = dynobj = abfd;
|
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;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -418,6 +435,12 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
if (sgot == NULL)
|
if (sgot == NULL)
|
||||||
{
|
{
|
||||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
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");
|
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
|
||||||
if (srelgot == NULL)
|
if (srelgot == NULL)
|
||||||
{
|
{
|
||||||
@ -432,7 +455,6 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BFD_ASSERT (sgot != NULL && srelgot != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h != 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))
|
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -477,41 +501,32 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
local_got_offsets[r_symndx] = sgot->_raw_size;
|
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;
|
sgot->_raw_size += 4;
|
||||||
srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_386_PLT32:
|
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
|
/* If this is a local symbol, we resolve it directly without
|
||||||
creating a procedure linkage table entry. */
|
creating a procedure linkage table entry. */
|
||||||
if (h == NULL)
|
if (h == NULL)
|
||||||
continue;
|
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. */
|
/* Make sure this symbol is output as a dynamic symbol. */
|
||||||
if (h->dynindx == -1)
|
if (h->dynindx == -1)
|
||||||
{
|
{
|
||||||
@ -519,15 +534,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
h->plt_offset = splt->_raw_size;
|
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -602,33 +609,42 @@ elf_i386_adjust_dynamic_symbol (info, h)
|
|||||||
|
|
||||||
/* Make sure we know what is going on here. */
|
/* Make sure we know what is going on here. */
|
||||||
BFD_ASSERT (dynobj != NULL
|
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
|
&& h->root.type == bfd_link_hash_defined
|
||||||
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
||||||
== bfd_target_elf_flavour)
|
== bfd_target_elf_flavour)
|
||||||
|
&& ((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
|
&& (elf_elfheader (h->root.u.def.section->owner)->e_type
|
||||||
== ET_DYN)
|
== ET_DYN)
|
||||||
&& h->root.u.def.section->output_section == NULL);
|
&& h->root.u.def.section->output_section == NULL)));
|
||||||
|
|
||||||
/* If this is a function, put it in the procedure linkage table. We
|
/* If this is a function, put it in the procedure linkage table. We
|
||||||
will fill in the contents of the procedure linkage table later,
|
will fill in the contents of the procedure linkage table later,
|
||||||
when we know the address of the .got section. */
|
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");
|
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
BFD_ASSERT (s != NULL);
|
BFD_ASSERT (s != NULL);
|
||||||
|
|
||||||
if (h->plt_offset != (bfd_vma) -1)
|
/* If this is the first .plt entry, make room for the special
|
||||||
{
|
first entry. */
|
||||||
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)
|
if (s->_raw_size == 0)
|
||||||
s->_raw_size += PLT_ENTRY_SIZE;
|
s->_raw_size += PLT_ENTRY_SIZE;
|
||||||
|
|
||||||
@ -641,9 +657,8 @@ elf_i386_adjust_dynamic_symbol (info, h)
|
|||||||
/* Make room for this entry. */
|
/* Make room for this entry. */
|
||||||
s->_raw_size += PLT_ENTRY_SIZE;
|
s->_raw_size += PLT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* We also need to make an entry in the .got.plt section,
|
/* We also need to make an entry in the .got.plt section, which
|
||||||
which will be placed in the .got section by the linker
|
will be placed in the .got section by the linker script. */
|
||||||
script. */
|
|
||||||
|
|
||||||
s = bfd_get_section_by_name (dynobj, ".got.plt");
|
s = bfd_get_section_by_name (dynobj, ".got.plt");
|
||||||
BFD_ASSERT (s != NULL);
|
BFD_ASSERT (s != NULL);
|
||||||
@ -654,7 +669,6 @@ elf_i386_adjust_dynamic_symbol (info, h)
|
|||||||
s = bfd_get_section_by_name (dynobj, ".rel.plt");
|
s = bfd_get_section_by_name (dynobj, ".rel.plt");
|
||||||
BFD_ASSERT (s != NULL);
|
BFD_ASSERT (s != NULL);
|
||||||
s->_raw_size += sizeof (Elf32_External_Rel);
|
s->_raw_size += sizeof (Elf32_External_Rel);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -751,6 +765,8 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
dynobj = elf_hash_table (info)->dynobj;
|
dynobj = elf_hash_table (info)->dynobj;
|
||||||
BFD_ASSERT (dynobj != NULL);
|
BFD_ASSERT (dynobj != NULL);
|
||||||
|
|
||||||
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
|
{
|
||||||
/* Set the contents of the .interp section to the interpreter. */
|
/* Set the contents of the .interp section to the interpreter. */
|
||||||
if (! info->shared)
|
if (! info->shared)
|
||||||
{
|
{
|
||||||
@ -759,6 +775,18 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
|
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
|
||||||
s->contents = (unsigned char *) 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
|
/* The check_relocs and adjust_dynamic_symbol entry points have
|
||||||
determined the sizes of the various dynamic sections. Allocate
|
determined the sizes of the various dynamic sections. Allocate
|
||||||
@ -859,11 +887,13 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add some entries to the .dynamic section. We fill in the values
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
later, in elf_i386_finish_dynamic_sections, but we must add the
|
{
|
||||||
entries now so that we get the correct size for the .dynamic
|
/* Add some entries to the .dynamic section. We fill in the
|
||||||
section. The DT_DEBUG entry is filled in by the dynamic linker
|
values later, in elf_i386_finish_dynamic_sections, but we
|
||||||
and used by the debugger. */
|
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 (! info->shared)
|
||||||
{
|
{
|
||||||
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
||||||
@ -893,6 +923,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
|||||||
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -910,7 +941,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
Elf_Internal_Rela *relocs;
|
Elf_Internal_Rela *relocs;
|
||||||
Elf_Internal_Sym *local_syms;
|
Elf_Internal_Sym *local_syms;
|
||||||
asection **local_sections;
|
asection **local_sections;
|
||||||
char *output_names;
|
|
||||||
{
|
{
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
@ -1026,8 +1056,33 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
BFD_ASSERT (h->got_offset != (bfd_vma) -1);
|
bfd_vma off;
|
||||||
relocation = sgot->output_offset + h->got_offset;
|
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -1044,12 +1099,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
if ((off & 1) != 0)
|
if ((off & 1) != 0)
|
||||||
off &= ~1;
|
off &= ~1;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
||||||
|
|
||||||
|
if (info->shared)
|
||||||
{
|
{
|
||||||
asection *srelgot;
|
asection *srelgot;
|
||||||
Elf_Internal_Rel outrel;
|
Elf_Internal_Rel outrel;
|
||||||
|
|
||||||
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
|
||||||
|
|
||||||
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
|
srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
|
||||||
BFD_ASSERT (srelgot != NULL);
|
BFD_ASSERT (srelgot != NULL);
|
||||||
|
|
||||||
@ -1062,6 +1119,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
srelgot->contents)
|
srelgot->contents)
|
||||||
+ srelgot->reloc_count));
|
+ srelgot->reloc_count));
|
||||||
++srelgot->reloc_count;
|
++srelgot->reloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
local_got_offsets[r_symndx] |= 1;
|
local_got_offsets[r_symndx] |= 1;
|
||||||
}
|
}
|
||||||
@ -1112,13 +1170,19 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
if (h == NULL)
|
if (h == NULL)
|
||||||
break;
|
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)
|
if (splt == NULL)
|
||||||
{
|
{
|
||||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
BFD_ASSERT (splt != NULL);
|
BFD_ASSERT (splt != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFD_ASSERT (h != NULL && h->plt_offset != (bfd_vma) -1);
|
|
||||||
relocation = (splt->output_section->vma
|
relocation = (splt->output_section->vma
|
||||||
+ splt->output_offset
|
+ splt->output_offset
|
||||||
+ h->plt_offset);
|
+ h->plt_offset);
|
||||||
@ -1161,7 +1225,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
+ input_section->output_offset);
|
+ input_section->output_offset);
|
||||||
if (r_type == R_386_PC32)
|
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);
|
outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1395,17 +1459,22 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
|
|||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
{
|
{
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
asection *splt;
|
|
||||||
asection *sgot;
|
asection *sgot;
|
||||||
asection *sdyn;
|
asection *sdyn;
|
||||||
Elf32_External_Dyn *dyncon, *dynconend;
|
|
||||||
|
|
||||||
dynobj = elf_hash_table (info)->dynobj;
|
dynobj = elf_hash_table (info)->dynobj;
|
||||||
|
|
||||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
|
||||||
sgot = bfd_get_section_by_name (dynobj, ".got.plt");
|
sgot = bfd_get_section_by_name (dynobj, ".got.plt");
|
||||||
|
BFD_ASSERT (sgot != NULL);
|
||||||
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
||||||
BFD_ASSERT (splt != NULL && sgot != NULL && sdyn != NULL);
|
|
||||||
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
|
{
|
||||||
|
asection *splt;
|
||||||
|
Elf32_External_Dyn *dyncon, *dynconend;
|
||||||
|
|
||||||
|
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
|
BFD_ASSERT (splt != NULL && sdyn != NULL);
|
||||||
|
|
||||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
||||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
||||||
@ -1445,15 +1514,15 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_RELSZ:
|
case DT_RELSZ:
|
||||||
/* My reading of the SVR4 ABI indicates that the procedure
|
/* My reading of the SVR4 ABI indicates that the
|
||||||
linkage table relocs (DT_JMPREL) should be included in
|
procedure linkage table relocs (DT_JMPREL) should be
|
||||||
the overall relocs (DT_REL). This is what Solaris does.
|
included in the overall relocs (DT_REL). This is
|
||||||
However, UnixWare can not handle that case. Therefore,
|
what Solaris does. However, UnixWare can not handle
|
||||||
we override the DT_RELSZ entry here to make it not
|
that case. Therefore, we override the DT_RELSZ entry
|
||||||
include the JMPREL relocs. Since the linker script
|
here to make it not include the JMPREL relocs. Since
|
||||||
arranges for .rel.plt to follow all other relocation
|
the linker script arranges for .rel.plt to follow all
|
||||||
sections, we don't have to worry about changing the
|
other relocation sections, we don't have to worry
|
||||||
DT_REL entry. */
|
about changing the DT_REL entry. */
|
||||||
s = bfd_get_section_by_name (output_bfd, ".rel.plt");
|
s = bfd_get_section_by_name (output_bfd, ".rel.plt");
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
{
|
{
|
||||||
@ -1484,9 +1553,17 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
/* Fill in the first three entries in the global offset table. */
|
||||||
if (sgot->_raw_size > 0)
|
if (sgot->_raw_size > 0)
|
||||||
{
|
{
|
||||||
|
if (sdyn == NULL)
|
||||||
|
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
|
||||||
|
else
|
||||||
bfd_put_32 (output_bfd,
|
bfd_put_32 (output_bfd,
|
||||||
sdyn->output_section->vma + sdyn->output_offset,
|
sdyn->output_section->vma + sdyn->output_offset,
|
||||||
sgot->contents);
|
sgot->contents);
|
||||||
@ -1496,10 +1573,6 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
|
|||||||
|
|
||||||
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ static void elf_info_to_howto
|
|||||||
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
|
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
|
||||||
static boolean elf32_sparc_create_dynamic_sections
|
static boolean elf32_sparc_create_dynamic_sections
|
||||||
PARAMS ((bfd *, struct bfd_link_info *));
|
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
|
static boolean elf32_sparc_check_relocs
|
||||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||||
const Elf_Internal_Rela *));
|
const Elf_Internal_Rela *));
|
||||||
@ -38,7 +40,7 @@ static boolean elf32_sparc_size_dynamic_sections
|
|||||||
PARAMS ((bfd *, struct bfd_link_info *));
|
PARAMS ((bfd *, struct bfd_link_info *));
|
||||||
static boolean elf32_sparc_relocate_section
|
static boolean elf32_sparc_relocate_section
|
||||||
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
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
|
static boolean elf32_sparc_finish_dynamic_symbol
|
||||||
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
|
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
|
||||||
Elf_Internal_Sym *));
|
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_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_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_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_PC22, 10,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_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_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_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),
|
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))
|
&& ! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* The first four entries in .plt are reserved. */
|
|
||||||
s->_raw_size = 4 * PLT_ENTRY_SIZE;
|
|
||||||
|
|
||||||
s = bfd_make_section (abfd, ".rela.plt");
|
s = bfd_make_section (abfd, ".rela.plt");
|
||||||
if (s == NULL
|
if (s == NULL
|
||||||
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|
||||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||||
return false;
|
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");
|
s = bfd_make_section (abfd, ".got");
|
||||||
if (s == NULL
|
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))
|
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -270,27 +312,6 @@ elf32_sparc_create_dynamic_sections (abfd, info)
|
|||||||
/* The first global offset table entry is reserved. */
|
/* The first global offset table entry is reserved. */
|
||||||
s->_raw_size += 4;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,8 +334,6 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
const Elf_Internal_Rela *rel_end;
|
const Elf_Internal_Rela *rel_end;
|
||||||
asection *sgot;
|
asection *sgot;
|
||||||
asection *srelgot;
|
asection *srelgot;
|
||||||
asection *splt;
|
|
||||||
asection *srelplt;
|
|
||||||
asection *sreloc;
|
asection *sreloc;
|
||||||
|
|
||||||
if (info->relocateable)
|
if (info->relocateable)
|
||||||
@ -327,8 +346,6 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
|
|
||||||
sgot = NULL;
|
sgot = NULL;
|
||||||
srelgot = NULL;
|
srelgot = NULL;
|
||||||
splt = NULL;
|
|
||||||
srelplt = NULL;
|
|
||||||
sreloc = NULL;
|
sreloc = NULL;
|
||||||
|
|
||||||
rel_end = relocs + sec->reloc_count;
|
rel_end = relocs + sec->reloc_count;
|
||||||
@ -343,27 +360,6 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
else
|
else
|
||||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
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))
|
switch (ELF32_R_TYPE (rel->r_info))
|
||||||
{
|
{
|
||||||
case R_SPARC_GOT10:
|
case R_SPARC_GOT10:
|
||||||
@ -371,9 +367,23 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
case R_SPARC_GOT22:
|
case R_SPARC_GOT22:
|
||||||
/* This symbol requires a global offset table entry. */
|
/* 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)
|
if (sgot == NULL)
|
||||||
{
|
{
|
||||||
sgot = bfd_get_section_by_name (dynobj, ".got");
|
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");
|
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||||
if (srelgot == NULL)
|
if (srelgot == NULL)
|
||||||
{
|
{
|
||||||
@ -384,10 +394,10 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
| SEC_LOAD
|
| SEC_LOAD
|
||||||
| SEC_HAS_CONTENTS
|
| SEC_HAS_CONTENTS
|
||||||
| SEC_IN_MEMORY
|
| SEC_IN_MEMORY
|
||||||
| SEC_READONLY)))
|
| SEC_READONLY))
|
||||||
|
|| ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BFD_ASSERT (sgot != NULL && srelgot != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
@ -398,6 +408,15 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
h->got_offset = sgot->_raw_size;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -425,15 +444,26 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
local_got_offsets[r_symndx] = sgot->_raw_size;
|
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;
|
sgot->_raw_size += 4;
|
||||||
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_SPARC_WPLT30:
|
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)
|
if (h == NULL)
|
||||||
{
|
{
|
||||||
@ -443,32 +473,14 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|
|||||||
return false;
|
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
|
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
|
||||||
procedure linkage table. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
h->plt_offset = splt->_raw_size;
|
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
|
||||||
|
|
||||||
/* Make room for this entry. */
|
|
||||||
splt->_raw_size += PLT_ENTRY_SIZE;
|
|
||||||
srelplt->_raw_size += sizeof (Elf32_External_Rela);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -560,26 +572,44 @@ elf32_sparc_adjust_dynamic_symbol (info, h)
|
|||||||
|
|
||||||
/* Make sure we know what is going on here. */
|
/* Make sure we know what is going on here. */
|
||||||
BFD_ASSERT (dynobj != NULL
|
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
|
&& h->root.type == bfd_link_hash_defined
|
||||||
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
||||||
== bfd_target_elf_flavour)
|
== bfd_target_elf_flavour)
|
||||||
|
&& ((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
|
&& (elf_elfheader (h->root.u.def.section->owner)->e_type
|
||||||
== ET_DYN)
|
== ET_DYN)
|
||||||
&& h->root.u.def.section->output_section == NULL);
|
&& h->root.u.def.section->output_section == NULL)));
|
||||||
|
|
||||||
/* If this is a function, put it in the procedure linkage table. We
|
/* If this is a function, put it in the procedure linkage table. We
|
||||||
will fill in the contents of the procedure linkage table later
|
will fill in the contents of the procedure linkage table later
|
||||||
(although we could actually do it here). */
|
(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)
|
||||||
{
|
{
|
||||||
|
/* 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");
|
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
BFD_ASSERT (s != NULL);
|
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. */
|
/* The procedure linkage table has a maximum size. */
|
||||||
if (s->_raw_size >= 0x400000)
|
if (s->_raw_size >= 0x400000)
|
||||||
{
|
{
|
||||||
@ -601,7 +631,6 @@ elf32_sparc_adjust_dynamic_symbol (info, h)
|
|||||||
s = bfd_get_section_by_name (dynobj, ".rela.plt");
|
s = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||||
BFD_ASSERT (s != NULL);
|
BFD_ASSERT (s != NULL);
|
||||||
s->_raw_size += sizeof (Elf32_External_Rela);
|
s->_raw_size += sizeof (Elf32_External_Rela);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -696,6 +725,8 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
dynobj = elf_hash_table (info)->dynobj;
|
dynobj = elf_hash_table (info)->dynobj;
|
||||||
BFD_ASSERT (dynobj != NULL);
|
BFD_ASSERT (dynobj != NULL);
|
||||||
|
|
||||||
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
|
{
|
||||||
/* Set the contents of the .interp section to the interpreter. */
|
/* Set the contents of the .interp section to the interpreter. */
|
||||||
if (! info->shared)
|
if (! info->shared)
|
||||||
{
|
{
|
||||||
@ -708,7 +739,20 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
/* Make space for the trailing nop in .plt. */
|
/* Make space for the trailing nop in .plt. */
|
||||||
s = bfd_get_section_by_name (dynobj, ".plt");
|
s = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
BFD_ASSERT (s != NULL);
|
BFD_ASSERT (s != NULL);
|
||||||
|
if (s->_raw_size > 0)
|
||||||
s->_raw_size += 4;
|
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
|
/* The check_relocs and adjust_dynamic_symbol entry points have
|
||||||
determined the sizes of the various dynamic sections. Allocate
|
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)
|
for (s = dynobj->sections; s != NULL; s = s->next)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
boolean strip;
|
||||||
|
|
||||||
if ((s->flags & SEC_IN_MEMORY) == 0)
|
if ((s->flags & SEC_IN_MEMORY) == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -725,8 +770,24 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
of the dynobj section names depend upon the input files. */
|
of the dynobj section names depend upon the input files. */
|
||||||
name = bfd_get_section_name (dynobj, s);
|
name = bfd_get_section_name (dynobj, s);
|
||||||
|
|
||||||
if (strncmp (name, ".rela", 5) == 0
|
strip = false;
|
||||||
&& s->_raw_size > 0)
|
|
||||||
|
if (strncmp (name, ".rela", 5) == 0)
|
||||||
|
{
|
||||||
|
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;
|
asection *target;
|
||||||
|
|
||||||
@ -737,10 +798,11 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
&& (target->flags & SEC_READONLY) != 0)
|
&& (target->flags & SEC_READONLY) != 0)
|
||||||
reltext = true;
|
reltext = true;
|
||||||
|
|
||||||
/* We use the reloc_count field as a counter if we need to
|
/* We use the reloc_count field as a counter if we need
|
||||||
copy relocs into the output file. */
|
to copy relocs into the output file. */
|
||||||
s->reloc_count = 0;
|
s->reloc_count = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (strcmp (name, ".plt") != 0
|
else if (strcmp (name, ".plt") != 0
|
||||||
&& strcmp (name, ".got") != 0)
|
&& strcmp (name, ".got") != 0)
|
||||||
{
|
{
|
||||||
@ -748,6 +810,20 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
continue;
|
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. */
|
/* Allocate memory for the section contents. */
|
||||||
s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
|
s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
|
||||||
if (s->contents == NULL && s->_raw_size != 0)
|
if (s->contents == NULL && s->_raw_size != 0)
|
||||||
@ -757,11 +833,13 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add some entries to the .dynamic section. We fill in the values
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
later, in elf32_sparc_finish_dynamic_sections, but we must add
|
{
|
||||||
the entries now so that we get the correct size for the .dynamic
|
/* Add some entries to the .dynamic section. We fill in the
|
||||||
section. The DT_DEBUG entry is filled in by the dynamic linker
|
values later, in elf32_sparc_finish_dynamic_sections, but we
|
||||||
and used by the debugger. */
|
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 (! info->shared)
|
||||||
{
|
{
|
||||||
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
|
||||||
@ -783,6 +861,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -791,8 +870,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
|
|||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
contents, relocs, local_syms, local_sections,
|
contents, relocs, local_syms, local_sections)
|
||||||
output_names)
|
|
||||||
bfd *output_bfd;
|
bfd *output_bfd;
|
||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
bfd *input_bfd;
|
bfd *input_bfd;
|
||||||
@ -801,7 +879,6 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
Elf_Internal_Rela *relocs;
|
Elf_Internal_Rela *relocs;
|
||||||
Elf_Internal_Sym *local_syms;
|
Elf_Internal_Sym *local_syms;
|
||||||
asection **local_sections;
|
asection **local_sections;
|
||||||
char *output_names;
|
|
||||||
{
|
{
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
@ -915,8 +992,33 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
BFD_ASSERT (h->got_offset != (bfd_vma) -1);
|
bfd_vma off;
|
||||||
relocation = sgot->output_offset + h->got_offset;
|
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -929,16 +1031,20 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
|
|
||||||
/* The offset must always be a multiple of 4. We use
|
/* The offset must always be a multiple of 4. We use
|
||||||
the least significant bit to record whether we have
|
the least significant bit to record whether we have
|
||||||
already generated the necessary reloc. */
|
already processed this entry. */
|
||||||
if ((off & 1) != 0)
|
if ((off & 1) != 0)
|
||||||
off &= ~1;
|
off &= ~1;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
||||||
|
|
||||||
|
if (info->shared)
|
||||||
{
|
{
|
||||||
asection *srelgot;
|
asection *srelgot;
|
||||||
Elf_Internal_Rela outrel;
|
Elf_Internal_Rela outrel;
|
||||||
|
|
||||||
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
/* We need to generate a R_SPARC_RELATIVE reloc
|
||||||
|
for the dynamic linker. */
|
||||||
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||||
BFD_ASSERT (srelgot != NULL);
|
BFD_ASSERT (srelgot != NULL);
|
||||||
|
|
||||||
@ -952,6 +1058,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
srelgot->contents)
|
srelgot->contents)
|
||||||
+ srelgot->reloc_count));
|
+ srelgot->reloc_count));
|
||||||
++srelgot->reloc_count;
|
++srelgot->reloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
local_got_offsets[r_symndx] |= 1;
|
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:
|
case R_SPARC_WPLT30:
|
||||||
/* Relocation is to the entry for this symbol in the
|
/* Relocation is to the entry for this symbol in the
|
||||||
procedure linkage table. */
|
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)
|
if (splt == NULL)
|
||||||
{
|
{
|
||||||
splt = bfd_get_section_by_name (dynobj, ".plt");
|
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
BFD_ASSERT (splt != NULL);
|
BFD_ASSERT (splt != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFD_ASSERT (h != NULL && h->plt_offset != (bfd_vma) -1);
|
|
||||||
relocation = (splt->output_section->vma
|
relocation = (splt->output_section->vma
|
||||||
+ splt->output_offset
|
+ splt->output_offset
|
||||||
+ h->plt_offset);
|
+ h->plt_offset);
|
||||||
@ -1029,7 +1144,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
+ input_section->output_offset);
|
+ input_section->output_offset);
|
||||||
if (h != NULL)
|
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_info = ELF32_R_INFO (h->dynindx, r_type);
|
||||||
outrel.r_addend = 0;
|
outrel.r_addend = 0;
|
||||||
}
|
}
|
||||||
@ -1098,7 +1213,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
name = h->root.root.string;
|
name = h->root.root.string;
|
||||||
else
|
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)
|
if (name == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (*name == '\0')
|
if (*name == '\0')
|
||||||
@ -1244,17 +1361,20 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
|
|||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
{
|
{
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
asection *splt;
|
|
||||||
asection *sgot;
|
|
||||||
asection *sdyn;
|
asection *sdyn;
|
||||||
Elf32_External_Dyn *dyncon, *dynconend;
|
asection *sgot;
|
||||||
|
|
||||||
dynobj = elf_hash_table (info)->dynobj;
|
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");
|
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
|
||||||
BFD_ASSERT (splt != NULL && sgot != NULL && sdyn != NULL);
|
|
||||||
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
|
{
|
||||||
|
asection *splt;
|
||||||
|
Elf32_External_Dyn *dyncon, *dynconend;
|
||||||
|
|
||||||
|
splt = bfd_get_section_by_name (dynobj, ".plt");
|
||||||
|
BFD_ASSERT (splt != NULL && sdyn != NULL);
|
||||||
|
|
||||||
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
dyncon = (Elf32_External_Dyn *) sdyn->contents;
|
||||||
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
|
||||||
@ -1293,8 +1413,8 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the first four entries in the procedure linkage table, and
|
/* Clear the first four entries in the procedure linkage table,
|
||||||
put a nop in the last four bytes. */
|
and put a nop in the last four bytes. */
|
||||||
if (splt->_raw_size > 0)
|
if (splt->_raw_size > 0)
|
||||||
{
|
{
|
||||||
memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
|
memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
|
||||||
@ -1302,16 +1422,25 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
|
|||||||
splt->contents + splt->_raw_size - 4);
|
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
|
/* Set the first entry in the global offset table to the address of
|
||||||
the dynamic section. */
|
the dynamic section. */
|
||||||
|
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||||
|
BFD_ASSERT (sgot != NULL);
|
||||||
if (sgot->_raw_size > 0)
|
if (sgot->_raw_size > 0)
|
||||||
|
{
|
||||||
|
if (sdyn == NULL)
|
||||||
|
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
|
||||||
|
else
|
||||||
bfd_put_32 (output_bfd,
|
bfd_put_32 (output_bfd,
|
||||||
sdyn->output_section->vma + sdyn->output_offset,
|
sdyn->output_section->vma + sdyn->output_offset,
|
||||||
sgot->contents);
|
sgot->contents);
|
||||||
|
}
|
||||||
|
|
||||||
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
142
bfd/elfcode.h
142
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
|
/* 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
|
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)
|
elf_link_record_dynamic_symbol (info, h)
|
||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
{
|
{
|
||||||
if (h->dynindx == -1)
|
if (h->dynindx == -1)
|
||||||
{
|
{
|
||||||
|
struct bfd_strtab_hash *dynstr;
|
||||||
|
|
||||||
h->dynindx = elf_hash_table (info)->dynsymcount;
|
h->dynindx = elf_hash_table (info)->dynsymcount;
|
||||||
++elf_hash_table (info)->dynsymcount;
|
++elf_hash_table (info)->dynsymcount;
|
||||||
h->dynstr_index =
|
|
||||||
(unsigned long) _bfd_stringtab_add (elf_hash_table (info)->dynstr,
|
dynstr = elf_hash_table (info)->dynstr;
|
||||||
h->root.root.string,
|
if (dynstr == NULL)
|
||||||
true, false);
|
{
|
||||||
|
/* 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)
|
if (h->dynstr_index == (unsigned long) -1)
|
||||||
return false;
|
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. FIXME: If there are no input BFD's of the same
|
||||||
format as the output, we can't make a shared library. */
|
format as the output, we can't make a shared library. */
|
||||||
if (info->shared
|
if (info->shared
|
||||||
&& elf_hash_table (info)->dynobj == NULL
|
&& ! elf_hash_table (info)->dynamic_sections_created
|
||||||
&& abfd->xvec == info->hash->creator)
|
&& abfd->xvec == info->hash->creator)
|
||||||
{
|
{
|
||||||
if (! elf_link_create_dynamic_sections (abfd, info))
|
if (! elf_link_create_dynamic_sections (abfd, info))
|
||||||
goto error_return;
|
goto error_return;
|
||||||
elf_hash_table (info)->dynobj = abfd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -4065,14 +4079,11 @@ elf_link_add_object_symbols (abfd, info)
|
|||||||
abfd->sections = NULL;
|
abfd->sections = NULL;
|
||||||
|
|
||||||
/* If this is the first dynamic object found in the link, create
|
/* If this is the first dynamic object found in the link, create
|
||||||
the special sections required for dynamic linking. We need
|
the special sections required for dynamic linking. */
|
||||||
to put them somewhere, and attaching them to the first
|
if (! elf_hash_table (info)->dynamic_sections_created)
|
||||||
dynamic object is as good place as any. */
|
|
||||||
if (elf_hash_table (info)->dynobj == NULL)
|
|
||||||
{
|
{
|
||||||
if (! elf_link_create_dynamic_sections (abfd, info))
|
if (! elf_link_create_dynamic_sections (abfd, info))
|
||||||
goto error_return;
|
goto error_return;
|
||||||
elf_hash_table (info)->dynobj = abfd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a DT_NEEDED entry for this dynamic object. */
|
/* 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
|
/* Create some sections which will be filled in with dynamic linking
|
||||||
information. The ABFD argument is an input file which is a dynamic
|
information. ABFD is an input file which requires dynamic sections
|
||||||
object. The dynamic sections take up virtual memory space when the
|
to be created. The dynamic sections take up virtual memory space
|
||||||
final executable is run, so we need to create them before addresses
|
when the final executable is run, so we need to create them before
|
||||||
are assigned to the output sections. We work out the actual
|
addresses are assigned to the output sections. We work out the
|
||||||
contents and size of these sections later. */
|
actual contents and size of these sections later. */
|
||||||
|
|
||||||
boolean
|
boolean
|
||||||
elf_link_create_dynamic_sections (abfd, info)
|
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_link_hash_entry *h;
|
||||||
struct elf_backend_data *bed;
|
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
|
/* Note that we set the SEC_IN_MEMORY flag for all of these
|
||||||
sections. */
|
sections. */
|
||||||
flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
|
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))
|
|| ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* The first .dynsym symbol is a dummy. */
|
|
||||||
elf_hash_table (info)->dynsymcount = 1;
|
|
||||||
|
|
||||||
s = bfd_make_section (abfd, ".dynstr");
|
s = bfd_make_section (abfd, ".dynstr");
|
||||||
if (s == NULL
|
if (s == NULL
|
||||||
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
|
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Create a strtab to hold the dynamic symbol names. */
|
/* Create a strtab to hold the dynamic symbol names. */
|
||||||
|
if (elf_hash_table (info)->dynstr == NULL)
|
||||||
|
{
|
||||||
elf_hash_table (info)->dynstr = elf_stringtab_init ();
|
elf_hash_table (info)->dynstr = elf_stringtab_init ();
|
||||||
if (elf_hash_table (info)->dynstr == NULL)
|
if (elf_hash_table (info)->dynstr == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
s = bfd_make_section (abfd, ".dynamic");
|
s = bfd_make_section (abfd, ".dynamic");
|
||||||
if (s == NULL
|
if (s == NULL
|
||||||
@ -4550,7 +4570,12 @@ elf_link_create_dynamic_sections (abfd, info)
|
|||||||
backend set the right flags. The backend will normally create
|
backend set the right flags. The backend will normally create
|
||||||
the .got and .plt sections. */
|
the .got and .plt sections. */
|
||||||
bed = get_elf_backend_data (abfd);
|
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. */
|
/* Add an entry to the .dynamic table. */
|
||||||
@ -4777,7 +4802,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|
|||||||
asection **sinterpptr;
|
asection **sinterpptr;
|
||||||
{
|
{
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
size_t dynsymcount;
|
|
||||||
asection *s;
|
asection *s;
|
||||||
Elf_Internal_Sym isym;
|
Elf_Internal_Sym isym;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -4787,22 +4811,27 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|
|||||||
*sinterpptr = NULL;
|
*sinterpptr = NULL;
|
||||||
|
|
||||||
dynobj = elf_hash_table (info)->dynobj;
|
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
|
/* If there were no dynamic objects in the link, there is nothing to
|
||||||
do here. */
|
do here. */
|
||||||
if (dynobj == NULL)
|
if (dynobj == NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
|
{
|
||||||
|
size_t dynsymcount;
|
||||||
|
bfd_size_type strsize;
|
||||||
|
|
||||||
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
|
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
|
||||||
BFD_ASSERT (*sinterpptr != NULL || info->shared);
|
BFD_ASSERT (*sinterpptr != NULL || info->shared);
|
||||||
|
|
||||||
/* Set the size of the .dynsym and .hash sections. We counted the
|
/* Set the size of the .dynsym and .hash sections. We counted
|
||||||
number of dynamic symbols in elf_link_add_object_symbols. We
|
the number of dynamic symbols in elf_link_add_object_symbols.
|
||||||
will build the contents of .dynsym and .hash when we build the
|
We will build the contents of .dynsym and .hash when we build
|
||||||
final symbol table, because until then we do not know the correct
|
the final symbol table, because until then we do not know the
|
||||||
value to give the symbols. We built the .dynstr section as we
|
correct value to give the symbols. We built the .dynstr
|
||||||
went along in elf_link_add_object_symbols. */
|
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");
|
s = bfd_get_section_by_name (dynobj, ".dynsym");
|
||||||
BFD_ASSERT (s != NULL);
|
BFD_ASSERT (s != NULL);
|
||||||
s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
|
s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
|
||||||
@ -4891,15 +4920,15 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|
|||||||
if (! elf_add_dynamic_entry (info, DT_FINI, 0))
|
if (! elf_add_dynamic_entry (info, DT_FINI, 0))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
|
||||||
if (! elf_add_dynamic_entry (info, DT_HASH, 0)
|
if (! elf_add_dynamic_entry (info, DT_HASH, 0)
|
||||||
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|
||||||
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|
||||||
|| ! elf_add_dynamic_entry (info, DT_STRSZ,
|
|| ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
|
||||||
_bfd_stringtab_size (elf_hash_table (info)
|
|
||||||
->dynstr))
|
|
||||||
|| ! elf_add_dynamic_entry (info, DT_SYMENT,
|
|| ! elf_add_dynamic_entry (info, DT_SYMENT,
|
||||||
sizeof (Elf_External_Sym)))
|
sizeof (Elf_External_Sym)))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* The backend must work out the sizes of all the other dynamic
|
/* The backend must work out the sizes of all the other dynamic
|
||||||
sections. */
|
sections. */
|
||||||
@ -4907,7 +4936,13 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|
|||||||
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
|
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
|
||||||
return false;
|
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
|
/* 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;
|
bfd *dynobj;
|
||||||
struct elf_backend_data *bed;
|
struct elf_backend_data *bed;
|
||||||
|
|
||||||
/* If this symbol is not defined by a dynamic object, or is not
|
/* If this symbol does not require a PLT entry, and it is not
|
||||||
referenced by a regular object, ignore it. FIXME: Do we need to
|
defined by a dynamic object, or is not referenced by a regular
|
||||||
worry about symbols which are defined by one dynamic object and
|
object, ignore it. FIXME: Do we need to worry about symbols
|
||||||
referenced by another one? */
|
which are defined by one dynamic object and referenced by another
|
||||||
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
|
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_DEF_DYNAMIC) == 0
|
||||||
|| (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
|
|| (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* If we've already adjusted this symbol, don't do it again. This
|
/* 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;
|
bfd *abfd;
|
||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
{
|
{
|
||||||
|
boolean dynamic;
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
struct elf_final_link_info finfo;
|
struct elf_final_link_info finfo;
|
||||||
register asection *o;
|
register asection *o;
|
||||||
@ -5088,6 +5126,7 @@ elf_bfd_final_link (abfd, info)
|
|||||||
if (info->shared)
|
if (info->shared)
|
||||||
abfd->flags |= DYNAMIC;
|
abfd->flags |= DYNAMIC;
|
||||||
|
|
||||||
|
dynamic = elf_hash_table (info)->dynamic_sections_created;
|
||||||
dynobj = elf_hash_table (info)->dynobj;
|
dynobj = elf_hash_table (info)->dynobj;
|
||||||
|
|
||||||
finfo.info = info;
|
finfo.info = info;
|
||||||
@ -5095,7 +5134,7 @@ elf_bfd_final_link (abfd, info)
|
|||||||
finfo.symstrtab = elf_stringtab_init ();
|
finfo.symstrtab = elf_stringtab_init ();
|
||||||
if (finfo.symstrtab == NULL)
|
if (finfo.symstrtab == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (dynobj == NULL)
|
if (! dynamic)
|
||||||
{
|
{
|
||||||
finfo.dynsym_sec = NULL;
|
finfo.dynsym_sec = NULL;
|
||||||
finfo.hash_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
|
/* The sh_info field records the index of the first non local
|
||||||
symbol. */
|
symbol. */
|
||||||
symtab_hdr->sh_info = abfd->symcount;
|
symtab_hdr->sh_info = abfd->symcount;
|
||||||
if (dynobj != NULL)
|
if (dynamic)
|
||||||
elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
|
elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
|
||||||
|
|
||||||
/* We get the global symbols from the hash table. */
|
/* We get the global symbols from the hash table. */
|
||||||
@ -5500,9 +5539,9 @@ elf_bfd_final_link (abfd, info)
|
|||||||
o->reloc_count = 0;
|
o->reloc_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are linking against a dynamic object, finish up the dynamic
|
/* If we are linking against a dynamic object, or generating a
|
||||||
linking information. */
|
shared library, finish up the dynamic linking information. */
|
||||||
if (dynobj != NULL)
|
if (dynamic)
|
||||||
{
|
{
|
||||||
Elf_External_Dyn *dyncon, *dynconend;
|
Elf_External_Dyn *dyncon, *dynconend;
|
||||||
|
|
||||||
@ -5577,13 +5616,18 @@ elf_bfd_final_link (abfd, info)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have created any dynamic sections, then output them. */
|
||||||
|
if (dynobj != NULL)
|
||||||
|
{
|
||||||
if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
|
if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
|
||||||
goto error_return;
|
goto error_return;
|
||||||
|
|
||||||
for (o = dynobj->sections; o != NULL; o = o->next)
|
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;
|
continue;
|
||||||
if ((o->flags & SEC_IN_MEMORY) == 0)
|
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
|
/* 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
|
there now. We have already know the symbol index. We also fill
|
||||||
in the entry in the .hash section. */
|
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;
|
struct elf_backend_data *bed;
|
||||||
size_t bucketcount;
|
size_t bucketcount;
|
||||||
@ -5885,7 +5930,8 @@ elf_link_output_extsym (h, data)
|
|||||||
+ h->dynindx));
|
+ h->dynindx));
|
||||||
|
|
||||||
bucketcount = elf_hash_table (finfo->info)->bucketcount;
|
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
|
bucketpos = ((bfd_byte *) finfo->hash_sec->contents
|
||||||
+ (bucket + 2) * (ARCH_SIZE / 8));
|
+ (bucket + 2) * (ARCH_SIZE / 8));
|
||||||
chain = get_word (finfo->output_bfd, bucketpos);
|
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
|
#define ELF_LINK_HASH_DEFINED_WEAK 040
|
||||||
/* Symbol needs a copy reloc. */
|
/* Symbol needs a copy reloc. */
|
||||||
#define ELF_LINK_HASH_NEEDS_COPY 0100
|
#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. */
|
/* ELF linker hash table. */
|
||||||
@ -128,9 +130,12 @@ struct elf_link_hash_entry
|
|||||||
struct elf_link_hash_table
|
struct elf_link_hash_table
|
||||||
{
|
{
|
||||||
struct bfd_link_hash_table root;
|
struct bfd_link_hash_table root;
|
||||||
/* The first dynamic object found during a link. We create several
|
/* Whether we have created the special dynamic sections required
|
||||||
special input sections when linking against dynamic objects, and
|
when linking against or generating a shared object. */
|
||||||
we simply attach them to the first one found. */
|
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;
|
bfd *dynobj;
|
||||||
/* The number of symbols found in the link which must be put into
|
/* The number of symbols found in the link which must be put into
|
||||||
the .dynsym section. */
|
the .dynsym section. */
|
||||||
|
Reference in New Issue
Block a user