version 1.3, 2018/04/14 15:49:39 |
version 1.4, 2020/04/03 17:51:04 |
|
|
/* 32-bit ELF support for Nios II. |
/* 32-bit ELF support for Nios II. |
Copyright (C) 2012-2016 Free Software Foundation, Inc. |
Copyright (C) 2012-2018 Free Software Foundation, Inc. |
Contributed by Nigel Gray (ngray@altera.com). |
Contributed by Nigel Gray (ngray@altera.com). |
Contributed by Mentor Graphics, Inc. |
Contributed by Mentor Graphics, Inc. |
|
|
|
|
#include "elf/nios2.h" |
#include "elf/nios2.h" |
#include "opcode/nios2.h" |
#include "opcode/nios2.h" |
#include "elf32-nios2.h" |
#include "elf32-nios2.h" |
|
#include "libiberty.h" |
|
|
/* Use RELA relocations. */ |
/* Use RELA relocations. */ |
#ifndef USE_RELA |
#ifndef USE_RELA |
Line 1400 static reloc_howto_type elf_nios2_r2_how |
|
Line 1401 static reloc_howto_type elf_nios2_r2_how |
|
TRUE, |
TRUE, |
6, |
6, |
complain_overflow_signed, |
complain_overflow_signed, |
bfd_elf_generic_reloc, /* FIXME? */ |
bfd_elf_generic_reloc, /* FIXME? */ |
"R_NIOS2_R2_I10_1_PCREL", |
"R_NIOS2_R2_I10_1_PCREL", |
FALSE, |
FALSE, |
0xffc0, |
0xffc0, |
Line 1578 lookup_howto (unsigned int rtype, bfd *a |
|
Line 1579 lookup_howto (unsigned int rtype, bfd *a |
|
int i; |
int i; |
/* R2 relocations are a superset of R1, so use that for the lookup |
/* R2 relocations are a superset of R1, so use that for the lookup |
table. */ |
table. */ |
int r1_howto_tbl_size = (int) (sizeof (elf_nios2_r1_howto_table_rel) |
int r1_howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r1_howto_table_rel); |
/ sizeof (elf_nios2_r1_howto_table_rel[0])); |
int r2_howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r2_howto_table_rel); |
int r2_howto_tbl_size = (int) (sizeof (elf_nios2_r2_howto_table_rel) |
|
/ sizeof (elf_nios2_r2_howto_table_rel[0])); |
|
|
|
if (!initialized) |
if (!initialized) |
{ |
{ |
Line 1597 lookup_howto (unsigned int rtype, bfd *a |
|
Line 1596 lookup_howto (unsigned int rtype, bfd *a |
|
} |
} |
} |
} |
|
|
BFD_ASSERT (rtype <= R_NIOS2_ILLEGAL); |
if (rtype > R_NIOS2_ILLEGAL) |
|
return NULL; |
i = elf_code_to_howto_index[rtype]; |
i = elf_code_to_howto_index[rtype]; |
if (BFD_IS_R2 (abfd)) |
if (BFD_IS_R2 (abfd)) |
{ |
{ |
if (i >= r2_howto_tbl_size) |
if (i >= r2_howto_tbl_size) |
return 0; |
return NULL; |
return elf_nios2_r2_howto_table_rel + i; |
return elf_nios2_r2_howto_table_rel + i; |
} |
} |
else |
else |
{ |
{ |
if (i >= r1_howto_tbl_size) |
if (i >= r1_howto_tbl_size) |
return 0; |
return NULL; |
return elf_nios2_r1_howto_table_rel + i; |
return elf_nios2_r1_howto_table_rel + i; |
} |
} |
} |
} |
Line 1620 struct elf_reloc_map |
|
Line 1620 struct elf_reloc_map |
|
enum elf_nios2_reloc_type elf_val; |
enum elf_nios2_reloc_type elf_val; |
}; |
}; |
|
|
static const struct elf_reloc_map nios2_reloc_map[] = { |
static const struct elf_reloc_map nios2_reloc_map[] = |
|
{ |
{BFD_RELOC_NONE, R_NIOS2_NONE}, |
{BFD_RELOC_NONE, R_NIOS2_NONE}, |
{BFD_RELOC_NIOS2_S16, R_NIOS2_S16}, |
{BFD_RELOC_NIOS2_S16, R_NIOS2_S16}, |
{BFD_RELOC_NIOS2_U16, R_NIOS2_U16}, |
{BFD_RELOC_NIOS2_U16, R_NIOS2_U16}, |
Line 1726 struct elf32_nios2_stub_hash_entry |
|
Line 1727 struct elf32_nios2_stub_hash_entry |
|
bfd_hash_lookup ((table), (string), (create), (copy))) |
bfd_hash_lookup ((table), (string), (create), (copy))) |
|
|
|
|
/* The Nios II linker needs to keep track of the number of relocs that it |
|
decides to copy as dynamic relocs in check_relocs for each symbol. |
|
This is so that it can later discard them if they are found to be |
|
unnecessary. We store the information in a field extending the |
|
regular ELF linker hash table. */ |
|
|
|
struct elf32_nios2_dyn_relocs |
|
{ |
|
struct elf32_nios2_dyn_relocs *next; |
|
|
|
/* The input section of the reloc. */ |
|
asection *sec; |
|
|
|
/* Total number of relocs copied for the input section. */ |
|
bfd_size_type count; |
|
|
|
/* Number of pc-relative relocs copied for the input section. */ |
|
bfd_size_type pc_count; |
|
}; |
|
|
|
/* Nios II ELF linker hash entry. */ |
/* Nios II ELF linker hash entry. */ |
|
|
struct elf32_nios2_link_hash_entry |
struct elf32_nios2_link_hash_entry |
Line 1757 struct elf32_nios2_link_hash_entry |
|
Line 1738 struct elf32_nios2_link_hash_entry |
|
struct elf32_nios2_stub_hash_entry *hsh_cache; |
struct elf32_nios2_stub_hash_entry *hsh_cache; |
|
|
/* Track dynamic relocs copied for this symbol. */ |
/* Track dynamic relocs copied for this symbol. */ |
struct elf32_nios2_dyn_relocs *dyn_relocs; |
struct elf_dyn_relocs *dyn_relocs; |
|
|
#define GOT_UNKNOWN 0 |
#define GOT_UNKNOWN 0 |
#define GOT_NORMAL 1 |
#define GOT_NORMAL 1 |
Line 1820 struct elf32_nios2_link_hash_table |
|
Line 1801 struct elf32_nios2_link_hash_table |
|
Elf_Internal_Sym **all_local_syms; |
Elf_Internal_Sym **all_local_syms; |
|
|
/* Short-cuts to get to dynamic linker sections. */ |
/* Short-cuts to get to dynamic linker sections. */ |
asection *sdynbss; |
|
asection *srelbss; |
|
asection *sbss; |
asection *sbss; |
|
|
/* GOT pointer symbol _gp_got. */ |
/* GOT pointer symbol _gp_got. */ |
Line 2225 nios2_add_stub (const char *stub_name, |
|
Line 2204 nios2_add_stub (const char *stub_name, |
|
TRUE, FALSE); |
TRUE, FALSE); |
if (hsh == NULL) |
if (hsh == NULL) |
{ |
{ |
(*_bfd_error_handler) (_("%B: cannot create stub entry %s"), |
/* xgettext:c-format */ |
section->owner, |
_bfd_error_handler (_("%pB: cannot create stub entry %s"), |
stub_name); |
section->owner, |
|
stub_name); |
return NULL; |
return NULL; |
} |
} |
|
|
Line 2916 nios2_elf32_build_stubs (struct bfd_link |
|
Line 2896 nios2_elf32_build_stubs (struct bfd_link |
|
object file when linking. */ |
object file when linking. */ |
|
|
static bfd_boolean |
static bfd_boolean |
nios2_elf32_merge_private_bfd_data (bfd *ibfd, bfd *obfd) |
nios2_elf32_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) |
{ |
{ |
|
bfd *obfd = info->output_bfd; |
flagword old_flags; |
flagword old_flags; |
flagword new_flags; |
flagword new_flags; |
|
|
Line 2925 nios2_elf32_merge_private_bfd_data (bfd |
|
Line 2906 nios2_elf32_merge_private_bfd_data (bfd |
|
return TRUE; |
return TRUE; |
|
|
/* Check if we have the same endianness. */ |
/* Check if we have the same endianness. */ |
if (! _bfd_generic_verify_endian_match (ibfd, obfd)) |
if (! _bfd_generic_verify_endian_match (ibfd, info)) |
return FALSE; |
return FALSE; |
|
|
new_flags = elf_elfheader (ibfd)->e_flags; |
new_flags = elf_elfheader (ibfd)->e_flags; |
Line 2945 nios2_elf32_merge_private_bfd_data (bfd |
|
Line 2926 nios2_elf32_merge_private_bfd_data (bfd |
|
case EF_NIOS2_ARCH_R2: |
case EF_NIOS2_ARCH_R2: |
if (bfd_big_endian (ibfd)) |
if (bfd_big_endian (ibfd)) |
{ |
{ |
(*_bfd_error_handler) |
_bfd_error_handler |
(_("error: %B: Big-endian R2 is not supported."), ibfd); |
(_("error: %pB: big-endian R2 is not supported"), ibfd); |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
return FALSE; |
return FALSE; |
} |
} |
Line 2960 nios2_elf32_merge_private_bfd_data (bfd |
|
Line 2941 nios2_elf32_merge_private_bfd_data (bfd |
|
{ |
{ |
/* So far, the only incompatible flags denote incompatible |
/* So far, the only incompatible flags denote incompatible |
architectures. */ |
architectures. */ |
(*_bfd_error_handler) |
_bfd_error_handler |
(_("error: %B: Conflicting CPU architectures %d/%d"), |
/* xgettext:c-format */ |
|
(_("error: %pB: conflicting CPU architectures %d/%d"), |
ibfd, new_flags, old_flags); |
ibfd, new_flags, old_flags); |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
return FALSE; |
return FALSE; |
} |
} |
|
|
/* Merge Tag_compatibility attributes and any common GNU ones. */ |
/* Merge Tag_compatibility attributes and any common GNU ones. */ |
_bfd_elf_merge_object_attributes (ibfd, obfd); |
_bfd_elf_merge_object_attributes (ibfd, info); |
|
|
return TRUE; |
return TRUE; |
} |
} |
|
|
|
|
/* Implement bfd_elf32_bfd_reloc_type_lookup: |
/* Implement bfd_elf32_bfd_reloc_type_lookup: |
Given a BFD reloc type, return a howto structure. */ |
Given a BFD reloc type, return a howto structure. */ |
|
|
static reloc_howto_type * |
static reloc_howto_type * |
nios2_elf32_bfd_reloc_type_lookup (bfd *abfd, |
nios2_elf32_bfd_reloc_type_lookup (bfd *abfd, |
bfd_reloc_code_real_type code) |
bfd_reloc_code_real_type code) |
{ |
{ |
int i; |
int i; |
|
|
for (i = 0; |
for (i = 0; i < (int) ARRAY_SIZE (nios2_reloc_map); ++i) |
i < (int) (sizeof (nios2_reloc_map) / sizeof (struct elf_reloc_map)); |
|
++i) |
|
if (nios2_reloc_map[i].bfd_val == code) |
if (nios2_reloc_map[i].bfd_val == code) |
return lookup_howto (nios2_reloc_map[i].elf_val, abfd); |
return lookup_howto (nios2_reloc_map[i].elf_val, abfd); |
return NULL; |
return NULL; |
Line 2992 nios2_elf32_bfd_reloc_type_lookup (bfd * |
|
Line 2972 nios2_elf32_bfd_reloc_type_lookup (bfd * |
|
|
|
/* Implement bfd_elf32_bfd_reloc_name_lookup: |
/* Implement bfd_elf32_bfd_reloc_name_lookup: |
Given a reloc name, return a howto structure. */ |
Given a reloc name, return a howto structure. */ |
|
|
static reloc_howto_type * |
static reloc_howto_type * |
nios2_elf32_bfd_reloc_name_lookup (bfd *abfd, |
nios2_elf32_bfd_reloc_name_lookup (bfd *abfd, |
const char *r_name) |
const char *r_name) |
Line 3003 nios2_elf32_bfd_reloc_name_lookup (bfd * |
|
Line 2984 nios2_elf32_bfd_reloc_name_lookup (bfd * |
|
if (BFD_IS_R2 (abfd)) |
if (BFD_IS_R2 (abfd)) |
{ |
{ |
howto_tbl = elf_nios2_r2_howto_table_rel; |
howto_tbl = elf_nios2_r2_howto_table_rel; |
howto_tbl_size = (int) (sizeof (elf_nios2_r2_howto_table_rel) |
howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r2_howto_table_rel); |
/ sizeof (elf_nios2_r2_howto_table_rel[0])); |
|
} |
} |
else |
else |
{ |
{ |
howto_tbl = elf_nios2_r1_howto_table_rel; |
howto_tbl = elf_nios2_r1_howto_table_rel; |
howto_tbl_size = (int) (sizeof (elf_nios2_r1_howto_table_rel) |
howto_tbl_size = (int) ARRAY_SIZE (elf_nios2_r1_howto_table_rel); |
/ sizeof (elf_nios2_r1_howto_table_rel[0])); |
|
} |
} |
|
|
for (i = 0; i < howto_tbl_size; i++) |
for (i = 0; i < howto_tbl_size; i++) |
if (howto_tbl[i].name && strcasecmp (howto_tbl[i].name, r_name) == 0) |
if (howto_tbl[i].name && strcasecmp (howto_tbl[i].name, r_name) == 0) |
return howto_tbl + i; |
return howto_tbl + i; |
|
|
return NULL; |
return NULL; |
} |
} |
|
|
/* Implement elf_info_to_howto: |
/* Implement elf_info_to_howto: |
Given a ELF32 relocation, fill in a arelent structure. */ |
Given a ELF32 relocation, fill in a arelent structure. */ |
static void |
|
|
static bfd_boolean |
nios2_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr, |
nios2_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr, |
Elf_Internal_Rela *dst) |
Elf_Internal_Rela *dst) |
{ |
{ |
unsigned int r_type; |
unsigned int r_type; |
|
|
r_type = ELF32_R_TYPE (dst->r_info); |
r_type = ELF32_R_TYPE (dst->r_info); |
cache_ptr->howto = lookup_howto (r_type, abfd); |
if ((cache_ptr->howto = lookup_howto (r_type, abfd)) == NULL) |
|
{ |
|
/* xgettext:c-format */ |
|
_bfd_error_handler (_("%pB: unsupported relocation type %#x"), |
|
abfd, r_type); |
|
bfd_set_error (bfd_error_bad_value); |
|
return FALSE; |
|
} |
|
return TRUE; |
} |
} |
|
|
/* Return the base VMA address which should be subtracted from real addresses |
/* Return the base VMA address which should be subtracted from real addresses |
Line 3712 nios2_elf32_relocate_section (bfd *outpu |
|
Line 3701 nios2_elf32_relocate_section (bfd *outpu |
|
splt = htab->root.splt; |
splt = htab->root.splt; |
local_got_offsets = elf_local_got_offsets (input_bfd); |
local_got_offsets = elf_local_got_offsets (input_bfd); |
|
|
if (elf32_nios2_hash_table (info)->h_gp_got == NULL) |
if (htab->h_gp_got == NULL) |
got_base = 0; |
got_base = 0; |
else |
else |
got_base = elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value; |
got_base = htab->h_gp_got->root.u.def.value; |
|
|
for (rel = relocs; rel < relend; rel++) |
for (rel = relocs; rel < relend; rel++) |
{ |
{ |
Line 3771 nios2_elf32_relocate_section (bfd *outpu |
|
Line 3760 nios2_elf32_relocate_section (bfd *outpu |
|
|
|
if (howto) |
if (howto) |
{ |
{ |
|
bfd_boolean resolved_to_zero; |
|
|
|
resolved_to_zero = (h != NULL |
|
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)); |
switch (howto->type) |
switch (howto->type) |
{ |
{ |
case R_NIOS2_HI16: |
case R_NIOS2_HI16: |
Line 3845 nios2_elf32_relocate_section (bfd *outpu |
|
Line 3838 nios2_elf32_relocate_section (bfd *outpu |
|
{ |
{ |
if (h) |
if (h) |
name = h->root.root.string; |
name = h->root.root.string; |
format = _("Unable to reach %s (at 0x%08x) from the " |
/* xgettext:c-format */ |
|
format = _("unable to reach %s (at 0x%08x) from the " |
"global pointer (at 0x%08x) because the " |
"global pointer (at 0x%08x) because the " |
"offset (%d) is out of the allowed range, " |
"offset (%d) is out of the allowed range, " |
"-32678 to 32767.\n" ); |
"-32678 to 32767\n" ); |
sprintf (msgbuf, format, name, symbol_address, gp, |
sprintf (msgbuf, format, name, symbol_address, gp, |
(signed)relocation); |
(signed)relocation); |
msg = msgbuf; |
msg = msgbuf; |
Line 3996 nios2_elf32_relocate_section (bfd *outpu |
|
Line 3990 nios2_elf32_relocate_section (bfd *outpu |
|
|
|
off = h->got.offset; |
off = h->got.offset; |
BFD_ASSERT (off != (bfd_vma) -1); |
BFD_ASSERT (off != (bfd_vma) -1); |
dyn = elf_hash_table (info)->dynamic_sections_created; |
dyn = htab->root.dynamic_sections_created; |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, |
bfd_link_pic (info), |
bfd_link_pic (info), |
h) |
h) |
|| (bfd_link_pic (info) |
|| (bfd_link_pic (info) |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
|| (ELF_ST_VISIBILITY (h->other) |
|| ((ELF_ST_VISIBILITY (h->other) |
|
|| resolved_to_zero) |
&& h->root.type == bfd_link_hash_undefweak)) |
&& h->root.type == bfd_link_hash_undefweak)) |
{ |
{ |
/* This is actually a static link, or it is a -Bsymbolic |
/* This is actually a static link, or it is a -Bsymbolic |
Line 4256 nios2_elf32_relocate_section (bfd *outpu |
|
Line 4251 nios2_elf32_relocate_section (bfd *outpu |
|
|
|
if ((bfd_link_pic (info) || indx != 0) |
if ((bfd_link_pic (info) || indx != 0) |
&& (h == NULL |
&& (h == NULL |
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|| (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|
&& !resolved_to_zero) |
|| h->root.type != bfd_link_hash_undefweak)) |
|| h->root.type != bfd_link_hash_undefweak)) |
{ |
{ |
need_relocs = TRUE; |
need_relocs = TRUE; |
Line 4365 nios2_elf32_relocate_section (bfd *outpu |
|
Line 4361 nios2_elf32_relocate_section (bfd *outpu |
|
case R_NIOS2_TLS_LE16: |
case R_NIOS2_TLS_LE16: |
if (bfd_link_dll (info)) |
if (bfd_link_dll (info)) |
{ |
{ |
(*_bfd_error_handler) |
_bfd_error_handler |
(_("%B(%A+0x%lx): R_NIOS2_TLS_LE16 relocation not " |
/* xgettext:c-format */ |
|
(_("%pB(%pA+%#" PRIx64 "): %s relocation not " |
"permitted in shared object"), |
"permitted in shared object"), |
input_bfd, input_section, |
input_bfd, input_section, |
(long) rel->r_offset, howto->name); |
(uint64_t) rel->r_offset, howto->name); |
return FALSE; |
return FALSE; |
} |
} |
else |
else |
Line 4384 nios2_elf32_relocate_section (bfd *outpu |
|
Line 4381 nios2_elf32_relocate_section (bfd *outpu |
|
if (bfd_link_pic (info) |
if (bfd_link_pic (info) |
&& (input_section->flags & SEC_ALLOC) != 0 |
&& (input_section->flags & SEC_ALLOC) != 0 |
&& (h == NULL |
&& (h == NULL |
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|| (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
|
&& !resolved_to_zero) |
|| h->root.type != bfd_link_hash_undefweak)) |
|| h->root.type != bfd_link_hash_undefweak)) |
{ |
{ |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
Line 4577 create_got_section (bfd *dynobj, struct |
|
Line 4575 create_got_section (bfd *dynobj, struct |
|
points to the base of the GOT while _gp_got may include a bias. */ |
points to the base of the GOT while _gp_got may include a bias. */ |
h = _bfd_elf_define_linkage_sym (dynobj, info, htab->root.sgotplt, |
h = _bfd_elf_define_linkage_sym (dynobj, info, htab->root.sgotplt, |
"_gp_got"); |
"_gp_got"); |
elf32_nios2_hash_table (info)->h_gp_got = h; |
htab->h_gp_got = h; |
if (h == NULL) |
if (h == NULL) |
return FALSE; |
return FALSE; |
|
|
Line 4597 nios2_elf32_create_dynamic_sections (bfd |
|
Line 4595 nios2_elf32_create_dynamic_sections (bfd |
|
if (!htab->root.sgot && !create_got_section (dynobj, info)) |
if (!htab->root.sgot && !create_got_section (dynobj, info)) |
return FALSE; |
return FALSE; |
|
|
_bfd_elf_create_dynamic_sections (dynobj, info); |
if (!_bfd_elf_create_dynamic_sections (dynobj, info)) |
|
return FALSE; |
|
|
/* In order for the two loads in a shared object .PLTresolve to share the |
/* In order for the two loads in a shared object .PLTresolve to share the |
same %hiadj, the start of the PLT (as well as the GOT) must be aligned |
same %hiadj, the start of the PLT (as well as the GOT) must be aligned |
to a 16-byte boundary. This is because the addresses for these loads |
to a 16-byte boundary. This is because the addresses for these loads |
include the -(.plt+4) PIC correction. */ |
include the -(.plt+4) PIC correction. */ |
if (!bfd_set_section_alignment (dynobj, htab->root.splt, 4)) |
return bfd_set_section_alignment (dynobj, htab->root.splt, 4); |
return FALSE; |
|
|
|
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); |
|
if (!htab->sdynbss) |
|
return FALSE; |
|
if (!bfd_link_pic (info)) |
|
{ |
|
htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); |
|
if (!htab->srelbss) |
|
return FALSE; |
|
} |
|
|
|
return TRUE; |
|
} |
} |
|
|
/* Implement elf_backend_copy_indirect_symbol: |
/* Implement elf_backend_copy_indirect_symbol: |
Line 4635 nios2_elf32_copy_indirect_symbol (struct |
|
Line 4621 nios2_elf32_copy_indirect_symbol (struct |
|
{ |
{ |
if (edir->dyn_relocs != NULL) |
if (edir->dyn_relocs != NULL) |
{ |
{ |
struct elf32_nios2_dyn_relocs **pp; |
struct elf_dyn_relocs **pp; |
struct elf32_nios2_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
|
|
/* Add reloc counts against the indirect sym to the direct sym |
/* Add reloc counts against the indirect sym to the direct sym |
list. Merge any entries against the same section. */ |
list. Merge any entries against the same section. */ |
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) |
for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) |
{ |
{ |
struct elf32_nios2_dyn_relocs *q; |
struct elf_dyn_relocs *q; |
|
|
for (q = edir->dyn_relocs; q != NULL; q = q->next) |
for (q = edir->dyn_relocs; q != NULL; q = q->next) |
if (q->sec == p->sec) |
if (q->sec == p->sec) |
Line 4703 static bfd_boolean |
|
Line 4689 static bfd_boolean |
|
nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, |
nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info, |
asection *sec, const Elf_Internal_Rela *relocs) |
asection *sec, const Elf_Internal_Rela *relocs) |
{ |
{ |
bfd *dynobj; |
|
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; |
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
struct elf32_nios2_link_hash_table *htab; |
struct elf32_nios2_link_hash_table *htab; |
asection *sgot; |
|
asection *srelgot; |
|
asection *sreloc = NULL; |
asection *sreloc = NULL; |
bfd_signed_vma *local_got_refcounts; |
bfd_signed_vma *local_got_refcounts; |
|
|
if (bfd_link_relocatable (info)) |
if (bfd_link_relocatable (info)) |
return TRUE; |
return TRUE; |
|
|
dynobj = elf_hash_table (info)->dynobj; |
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes_end = (sym_hashes |
sym_hashes_end = (sym_hashes |
Line 4727 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4709 nios2_elf32_check_relocs (bfd *abfd, str |
|
local_got_refcounts = elf_local_got_refcounts (abfd); |
local_got_refcounts = elf_local_got_refcounts (abfd); |
|
|
htab = elf32_nios2_hash_table (info); |
htab = elf32_nios2_hash_table (info); |
sgot = htab->root.sgot; |
|
srelgot = htab->root.srelgot; |
|
|
|
rel_end = relocs + sec->reloc_count; |
rel_end = relocs + sec->reloc_count; |
for (rel = relocs; rel < rel_end; rel++) |
for (rel = relocs; rel < rel_end; rel++) |
Line 4746 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4726 nios2_elf32_check_relocs (bfd *abfd, str |
|
while (h->root.type == bfd_link_hash_indirect |
while (h->root.type == bfd_link_hash_indirect |
|| h->root.type == bfd_link_hash_warning) |
|| h->root.type == bfd_link_hash_warning) |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
|
/* PR15323, ref flags aren't set for references in the same |
|
object. */ |
|
h->root.non_ir_ref = 1; |
|
} |
} |
|
|
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
Line 4787 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4763 nios2_elf32_check_relocs (bfd *abfd, str |
|
break; |
break; |
} |
} |
|
|
if (dynobj == NULL) |
|
{ |
|
/* Create the .got section. */ |
|
elf_hash_table (info)->dynobj = dynobj = abfd; |
|
nios2_elf32_create_dynamic_sections (dynobj, info); |
|
} |
|
|
|
if (sgot == NULL) |
|
{ |
|
sgot = htab->root.sgot; |
|
BFD_ASSERT (sgot != NULL); |
|
} |
|
|
|
if (srelgot == NULL |
|
&& (h != NULL || bfd_link_pic (info))) |
|
{ |
|
srelgot = htab->root.srelgot; |
|
BFD_ASSERT (srelgot != NULL); |
|
} |
|
|
|
if (h != NULL) |
if (h != NULL) |
{ |
{ |
struct elf32_nios2_link_hash_entry *eh |
struct elf32_nios2_link_hash_entry *eh |
Line 4865 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4821 nios2_elf32_check_relocs (bfd *abfd, str |
|
elf32_nios2_local_got_tls_type (abfd) [r_symndx] = tls_type; |
elf32_nios2_local_got_tls_type (abfd) [r_symndx] = tls_type; |
} |
} |
} |
} |
/* Fall through */ |
make_got: |
case R_NIOS2_TLS_LDM16: |
|
if (r_type == R_NIOS2_TLS_LDM16) |
|
htab->tls_ldm_got.refcount++; |
|
|
|
if (htab->root.sgot == NULL) |
if (htab->root.sgot == NULL) |
{ |
{ |
if (htab->root.dynobj == NULL) |
if (htab->root.dynobj == NULL) |
Line 4879 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4831 nios2_elf32_check_relocs (bfd *abfd, str |
|
} |
} |
break; |
break; |
|
|
|
case R_NIOS2_TLS_LDM16: |
|
htab->tls_ldm_got.refcount++; |
|
goto make_got; |
|
|
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
case R_NIOS2_GNU_VTINHERIT: |
case R_NIOS2_GNU_VTINHERIT: |
Line 4926 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4882 nios2_elf32_check_relocs (bfd *abfd, str |
|
|| (h != NULL && ! h->needs_plt |
|| (h != NULL && ! h->needs_plt |
&& (! SYMBOLIC_BIND (info, h) || ! h->def_regular)))) |
&& (! SYMBOLIC_BIND (info, h) || ! h->def_regular)))) |
{ |
{ |
struct elf32_nios2_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
struct elf32_nios2_dyn_relocs **head; |
struct elf_dyn_relocs **head; |
|
|
/* When creating a shared object, we must copy these |
/* When creating a shared object, we must copy these |
reloc types into the output file. We create a reloc |
reloc types into the output file. We create a reloc |
section in dynobj and make room for this reloc. */ |
section in dynobj and make room for this reloc. */ |
if (sreloc == NULL) |
if (sreloc == NULL) |
{ |
{ |
|
if (htab->root.dynobj == NULL) |
|
htab->root.dynobj = abfd; |
|
|
sreloc = _bfd_elf_make_dynamic_reloc_section |
sreloc = _bfd_elf_make_dynamic_reloc_section |
(sec, dynobj, 2, abfd, TRUE); |
(sec, htab->root.dynobj, 2, abfd, TRUE); |
if (sreloc == NULL) |
if (sreloc == NULL) |
return FALSE; |
return FALSE; |
} |
} |
Line 4964 nios2_elf32_check_relocs (bfd *abfd, str |
|
Line 4923 nios2_elf32_check_relocs (bfd *abfd, str |
|
s = sec; |
s = sec; |
|
|
vpp = &elf_section_data (s)->local_dynrel; |
vpp = &elf_section_data (s)->local_dynrel; |
head = (struct elf32_nios2_dyn_relocs **) vpp; |
head = (struct elf_dyn_relocs **) vpp; |
} |
} |
|
|
p = *head; |
p = *head; |
if (p == NULL || p->sec != sec) |
if (p == NULL || p->sec != sec) |
{ |
{ |
bfd_size_type amt = sizeof *p; |
bfd_size_type amt = sizeof *p; |
p = ((struct elf32_nios2_dyn_relocs *) |
p = ((struct elf_dyn_relocs *) |
bfd_alloc (htab->root.dynobj, amt)); |
bfd_alloc (htab->root.dynobj, amt)); |
if (p == NULL) |
if (p == NULL) |
return FALSE; |
return FALSE; |
Line 5013 nios2_elf32_gc_mark_hook (asection *sec, |
|
Line 4972 nios2_elf32_gc_mark_hook (asection *sec, |
|
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); |
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); |
} |
} |
|
|
/* Implement elf_backend_gc_sweep_hook: |
|
Update the got entry reference counts for the section being removed. */ |
|
static bfd_boolean |
|
nios2_elf32_gc_sweep_hook (bfd *abfd, |
|
struct bfd_link_info *info, |
|
asection *sec, |
|
const Elf_Internal_Rela *relocs) |
|
{ |
|
Elf_Internal_Shdr *symtab_hdr; |
|
struct elf_link_hash_entry **sym_hashes; |
|
bfd_signed_vma *local_got_refcounts; |
|
const Elf_Internal_Rela *rel, *relend; |
|
bfd *dynobj; |
|
|
|
if (bfd_link_relocatable (info)) |
|
return TRUE; |
|
|
|
elf_section_data (sec)->local_dynrel = NULL; |
|
|
|
dynobj = elf_hash_table (info)->dynobj; |
|
if (dynobj == NULL) |
|
return TRUE; |
|
|
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
|
sym_hashes = elf_sym_hashes (abfd); |
|
local_got_refcounts = elf_local_got_refcounts (abfd); |
|
|
|
relend = relocs + sec->reloc_count; |
|
for (rel = relocs; rel < relend; rel++) |
|
{ |
|
unsigned long r_symndx; |
|
struct elf_link_hash_entry *h = NULL; |
|
int r_type; |
|
|
|
r_symndx = ELF32_R_SYM (rel->r_info); |
|
if (r_symndx >= symtab_hdr->sh_info) |
|
{ |
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
|
while (h->root.type == bfd_link_hash_indirect |
|
|| h->root.type == bfd_link_hash_warning) |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
} |
|
|
|
r_type = ELF32_R_TYPE (rel->r_info); |
|
switch (r_type) |
|
{ |
|
case R_NIOS2_GOT16: |
|
case R_NIOS2_GOT_LO: |
|
case R_NIOS2_GOT_HA: |
|
case R_NIOS2_CALL16: |
|
case R_NIOS2_CALL_LO: |
|
case R_NIOS2_CALL_HA: |
|
if (h != NULL) |
|
{ |
|
if (h->got.refcount > 0) |
|
--h->got.refcount; |
|
} |
|
else if (local_got_refcounts != NULL) |
|
{ |
|
if (local_got_refcounts[r_symndx] > 0) |
|
--local_got_refcounts[r_symndx]; |
|
} |
|
break; |
|
|
|
case R_NIOS2_PCREL_LO: |
|
case R_NIOS2_PCREL_HA: |
|
case R_NIOS2_BFD_RELOC_32: |
|
case R_NIOS2_CALL26: |
|
case R_NIOS2_CALL26_NOAT: |
|
if (h != NULL) |
|
{ |
|
struct elf32_nios2_link_hash_entry *eh; |
|
struct elf32_nios2_dyn_relocs **pp; |
|
struct elf32_nios2_dyn_relocs *p; |
|
|
|
eh = (struct elf32_nios2_link_hash_entry *) h; |
|
|
|
if (h->plt.refcount > 0) |
|
--h->plt.refcount; |
|
|
|
if (r_type == R_NIOS2_PCREL_LO || r_type == R_NIOS2_PCREL_HA |
|
|| r_type == R_NIOS2_BFD_RELOC_32) |
|
{ |
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; |
|
pp = &p->next) |
|
if (p->sec == sec) |
|
{ |
|
p->count -= 1; |
|
if (p->count == 0) |
|
*pp = p->next; |
|
break; |
|
} |
|
} |
|
} |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
/* Implement elf_backend_finish_dynamic_symbols: |
/* Implement elf_backend_finish_dynamic_symbols: |
Finish up dynamic symbol handling. We set the contents of various |
Finish up dynamic symbol handling. We set the contents of various |
dynamic sections here. */ |
dynamic sections here. */ |
Line 5284 nios2_elf32_finish_dynamic_symbol (bfd * |
|
Line 5139 nios2_elf32_finish_dynamic_symbol (bfd * |
|
&& (h->root.type == bfd_link_hash_defined |
&& (h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak)); |
|| h->root.type == bfd_link_hash_defweak)); |
|
|
s = htab->srelbss; |
|
BFD_ASSERT (s != NULL); |
|
|
|
rela.r_offset = (h->root.u.def.value |
rela.r_offset = (h->root.u.def.value |
+ h->root.u.def.section->output_section->vma |
+ h->root.u.def.section->output_section->vma |
+ h->root.u.def.section->output_offset); |
+ h->root.u.def.section->output_offset); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY); |
rela.r_addend = 0; |
rela.r_addend = 0; |
|
if (h->root.u.def.section == htab->root.sdynrelro) |
|
s = htab->root.sreldynrelro; |
|
else |
|
s = htab->root.srelbss; |
|
BFD_ASSERT (s != NULL); |
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); |
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
} |
} |
|
|
/* Mark _DYNAMIC, _GLOBAL_OFFSET_TABLE_, and _gp_got as absolute. */ |
/* Mark _DYNAMIC, _GLOBAL_OFFSET_TABLE_, and _gp_got as absolute. */ |
if (strcmp (h->root.root.string, "_DYNAMIC") == 0 |
if (strcmp (h->root.root.string, "_DYNAMIC") == 0 |
|| h == elf_hash_table (info)->hgot |
|| h == htab->root.hgot |
|| h == elf32_nios2_hash_table (info)->h_gp_got) |
|| h == htab->h_gp_got) |
sym->st_shndx = SHN_ABS; |
sym->st_shndx = SHN_ABS; |
|
|
return TRUE; |
return TRUE; |
Line 5310 static bfd_boolean |
|
Line 5167 static bfd_boolean |
|
nios2_elf32_finish_dynamic_sections (bfd *output_bfd, |
nios2_elf32_finish_dynamic_sections (bfd *output_bfd, |
struct bfd_link_info *info) |
struct bfd_link_info *info) |
{ |
{ |
bfd *dynobj; |
|
asection *sgotplt; |
asection *sgotplt; |
asection *sdyn; |
asection *sdyn; |
struct elf32_nios2_link_hash_table *htab; |
struct elf32_nios2_link_hash_table *htab; |
|
|
htab = elf32_nios2_hash_table (info); |
htab = elf32_nios2_hash_table (info); |
dynobj = elf_hash_table (info)->dynobj; |
|
sgotplt = htab->root.sgotplt; |
sgotplt = htab->root.sgotplt; |
BFD_ASSERT (sgotplt != NULL); |
sdyn = NULL; |
sdyn = bfd_get_linker_section (dynobj, ".dynamic"); |
|
|
|
if (elf_hash_table (info)->dynamic_sections_created) |
if (htab->root.dynamic_sections_created) |
{ |
{ |
asection *splt; |
asection *splt; |
Elf32_External_Dyn *dyncon, *dynconend; |
Elf32_External_Dyn *dyncon, *dynconend; |
|
|
splt = htab->root.splt; |
splt = htab->root.splt; |
BFD_ASSERT (splt != NULL && sdyn != NULL); |
sdyn = bfd_get_linker_section (htab->root.dynobj, ".dynamic"); |
|
BFD_ASSERT (splt != NULL && sdyn != NULL && sgotplt != NULL); |
|
|
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); |
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); |
Line 5336 nios2_elf32_finish_dynamic_sections (bfd |
|
Line 5191 nios2_elf32_finish_dynamic_sections (bfd |
|
Elf_Internal_Dyn dyn; |
Elf_Internal_Dyn dyn; |
asection *s; |
asection *s; |
|
|
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); |
bfd_elf32_swap_dyn_in (htab->root.dynobj, dyncon, &dyn); |
|
|
switch (dyn.d_tag) |
switch (dyn.d_tag) |
{ |
{ |
Line 5361 nios2_elf32_finish_dynamic_sections (bfd |
|
Line 5216 nios2_elf32_finish_dynamic_sections (bfd |
|
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
break; |
break; |
|
|
case DT_RELASZ: |
|
/* The procedure linkage table relocs (DT_JMPREL) should |
|
not be included in the overall relocs (DT_RELA). |
|
Therefore, we override the DT_RELASZ entry here to |
|
make it not include the JMPREL relocs. Since the |
|
linker script arranges for .rela.plt to follow all |
|
other relocation sections, we don't have to worry |
|
about changing the DT_RELA entry. */ |
|
s = htab->root.srelplt; |
|
if (s != NULL) |
|
dyn.d_un.d_val -= s->size; |
|
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
|
break; |
|
|
|
case DT_NIOS2_GP: |
case DT_NIOS2_GP: |
s = htab->root.sgotplt; |
s = htab->root.sgotplt; |
dyn.d_un.d_ptr |
dyn.d_un.d_ptr |
Line 5434 nios2_elf32_finish_dynamic_sections (bfd |
|
Line 5275 nios2_elf32_finish_dynamic_sections (bfd |
|
} |
} |
} |
} |
} |
} |
|
|
/* Fill in the first three entries in the global offset table. */ |
/* Fill in the first three entries in the global offset table. */ |
if (sgotplt->size > 0) |
if (sgotplt != NULL && sgotplt->size > 0) |
{ |
{ |
if (sdyn == NULL) |
if (sdyn == NULL) |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents); |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents); |
Line 5445 nios2_elf32_finish_dynamic_sections (bfd |
|
Line 5287 nios2_elf32_finish_dynamic_sections (bfd |
|
sgotplt->contents); |
sgotplt->contents); |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 4); |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 4); |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 8); |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 8); |
} |
|
|
|
elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; |
if (sgotplt->output_section != bfd_abs_section_ptr) |
|
elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; |
|
} |
|
|
return TRUE; |
return TRUE; |
} |
} |
Line 5464 nios2_elf32_adjust_dynamic_symbol (struc |
|
Line 5307 nios2_elf32_adjust_dynamic_symbol (struc |
|
{ |
{ |
struct elf32_nios2_link_hash_table *htab; |
struct elf32_nios2_link_hash_table *htab; |
bfd *dynobj; |
bfd *dynobj; |
asection *s; |
asection *s, *srel; |
unsigned align2; |
unsigned align2; |
|
|
htab = elf32_nios2_hash_table (info); |
htab = elf32_nios2_hash_table (info); |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = htab->root.dynobj; |
|
|
/* 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->needs_plt |
&& (h->needs_plt |
|| h->u.weakdef != NULL |
|| h->is_weakalias |
|| (h->def_dynamic |
|| (h->def_dynamic |
&& h->ref_regular |
&& h->ref_regular |
&& !h->def_regular))); |
&& !h->def_regular))); |
Line 5507 nios2_elf32_adjust_dynamic_symbol (struc |
|
Line 5350 nios2_elf32_adjust_dynamic_symbol (struc |
|
/* If this is a weak symbol, and there is a real definition, the |
/* If this is a weak symbol, and there is a real definition, the |
processor independent code will have arranged for us to see the |
processor independent code will have arranged for us to see the |
real definition first, and we can just use the same value. */ |
real definition first, and we can just use the same value. */ |
if (h->u.weakdef != NULL) |
if (h->is_weakalias) |
{ |
{ |
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined |
struct elf_link_hash_entry *def = weakdef (h); |
|| h->u.weakdef->root.type == bfd_link_hash_defweak); |
BFD_ASSERT (def->root.type == bfd_link_hash_defined); |
h->root.u.def.section = h->u.weakdef->root.u.def.section; |
h->root.u.def.section = def->root.u.def.section; |
h->root.u.def.value = h->u.weakdef->root.u.def.value; |
h->root.u.def.value = def->root.u.def.value; |
return TRUE; |
return TRUE; |
} |
} |
|
|
Line 5532 nios2_elf32_adjust_dynamic_symbol (struc |
|
Line 5375 nios2_elf32_adjust_dynamic_symbol (struc |
|
|
|
if (h->size == 0) |
if (h->size == 0) |
{ |
{ |
(*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), |
_bfd_error_handler (_("dynamic variable `%s' is zero size"), |
h->root.root.string); |
h->root.root.string); |
return TRUE; |
return TRUE; |
} |
} |
|
|
Line 5546 nios2_elf32_adjust_dynamic_symbol (struc |
|
Line 5389 nios2_elf32_adjust_dynamic_symbol (struc |
|
determine the address it must put in the global offset table, so |
determine the address it must put in the global offset table, so |
both the dynamic object and the regular object will refer to the |
both the dynamic object and the regular object will refer to the |
same memory location for the variable. */ |
same memory location for the variable. */ |
s = htab->sdynbss; |
|
BFD_ASSERT (s != NULL); |
|
|
|
/* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to |
/* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to |
copy the initial value out of the dynamic object and into the |
copy the initial value out of the dynamic object and into the |
runtime process image. We need to remember the offset into the |
runtime process image. We need to remember the offset into the |
.rela.bss section we are going to use. */ |
.rela.bss section we are going to use. */ |
|
if ((h->root.u.def.section->flags & SEC_READONLY) != 0) |
|
{ |
|
s = htab->root.sdynrelro; |
|
srel = htab->root.sreldynrelro; |
|
} |
|
else |
|
{ |
|
s = htab->root.sdynbss; |
|
srel = htab->root.srelbss; |
|
} |
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) |
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) |
{ |
{ |
asection *srel; |
|
|
|
srel = htab->srelbss; |
|
BFD_ASSERT (srel != NULL); |
|
srel->size += sizeof (Elf32_External_Rela); |
srel->size += sizeof (Elf32_External_Rela); |
h->needs_copy = 1; |
h->needs_copy = 1; |
} |
} |
Line 5619 allocate_dynrelocs (struct elf_link_hash |
|
Line 5465 allocate_dynrelocs (struct elf_link_hash |
|
struct bfd_link_info *info; |
struct bfd_link_info *info; |
struct elf32_nios2_link_hash_table *htab; |
struct elf32_nios2_link_hash_table *htab; |
struct elf32_nios2_link_hash_entry *eh; |
struct elf32_nios2_link_hash_entry *eh; |
struct elf32_nios2_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
int use_plt; |
int use_plt; |
|
|
if (h->root.type == bfd_link_hash_indirect) |
if (h->root.type == bfd_link_hash_indirect) |
Line 5775 allocate_dynrelocs (struct elf_link_hash |
|
Line 5621 allocate_dynrelocs (struct elf_link_hash |
|
if (h->def_regular |
if (h->def_regular |
&& (h->forced_local || SYMBOLIC_BIND (info, h))) |
&& (h->forced_local || SYMBOLIC_BIND (info, h))) |
{ |
{ |
struct elf32_nios2_dyn_relocs **pp; |
struct elf_dyn_relocs **pp; |
|
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) |
{ |
{ |
Line 5793 allocate_dynrelocs (struct elf_link_hash |
|
Line 5639 allocate_dynrelocs (struct elf_link_hash |
|
if (eh->dyn_relocs != NULL |
if (eh->dyn_relocs != NULL |
&& h->root.type == bfd_link_hash_undefweak) |
&& h->root.type == bfd_link_hash_undefweak) |
{ |
{ |
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) |
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
|
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) |
eh->dyn_relocs = NULL; |
eh->dyn_relocs = NULL; |
|
|
/* Make sure undefined weak symbols are output as a dynamic |
/* Make sure undefined weak symbols are output as a dynamic |
Line 5852 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5699 nios2_elf32_size_dynamic_sections (bfd * |
|
{ |
{ |
bfd *dynobj; |
bfd *dynobj; |
asection *s; |
asection *s; |
bfd_boolean plt; |
|
bfd_boolean got; |
|
bfd_boolean relocs; |
bfd_boolean relocs; |
bfd *ibfd; |
bfd *ibfd; |
struct elf32_nios2_link_hash_table *htab; |
struct elf32_nios2_link_hash_table *htab; |
|
|
htab = elf32_nios2_hash_table (info); |
htab = elf32_nios2_hash_table (info); |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = htab->root.dynobj; |
BFD_ASSERT (dynobj != NULL); |
BFD_ASSERT (dynobj != NULL); |
|
|
htab->res_n_size = 0; |
htab->res_n_size = 0; |
if (elf_hash_table (info)->dynamic_sections_created) |
if (htab->root.dynamic_sections_created) |
{ |
{ |
/* Set the contents of the .interp section to the interpreter. */ |
/* Set the contents of the .interp section to the interpreter. */ |
if (bfd_link_executable (info) && !info->nointerp) |
if (bfd_link_executable (info) && !info->nointerp) |
Line 5902 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5747 nios2_elf32_size_dynamic_sections (bfd * |
|
|
|
for (s = ibfd->sections; s != NULL; s = s->next) |
for (s = ibfd->sections; s != NULL; s = s->next) |
{ |
{ |
struct elf32_nios2_dyn_relocs *p; |
struct elf_dyn_relocs *p; |
|
|
for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) |
for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) |
{ |
{ |
Line 5971 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5816 nios2_elf32_size_dynamic_sections (bfd * |
|
sym dynamic relocs. */ |
sym dynamic relocs. */ |
elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info); |
elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info); |
|
|
if (elf_hash_table (info)->dynamic_sections_created) |
if (htab->root.dynamic_sections_created) |
{ |
{ |
/* If the .got section is more than 0x8000 bytes, we add |
/* If the .got section is more than 0x8000 bytes, we add |
0x8000 to the value of _gp_got, so that 16-bit relocations |
0x8000 to the value of _gp_got, so that 16-bit relocations |
have a greater chance of working. */ |
have a greater chance of working. */ |
if (htab->root.sgot->size >= 0x8000 |
if (htab->root.sgot->size >= 0x8000 |
&& elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value == 0) |
&& htab->h_gp_got->root.u.def.value == 0) |
elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value = 0x8000; |
htab->h_gp_got->root.u.def.value = 0x8000; |
} |
} |
|
|
/* 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 |
memory for them. */ |
memory for them. */ |
plt = FALSE; |
|
got = FALSE; |
|
relocs = FALSE; |
relocs = FALSE; |
for (s = dynobj->sections; s != NULL; s = s->next) |
for (s = dynobj->sections; s != NULL; s = s->next) |
{ |
{ |
Line 5998 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5841 nios2_elf32_size_dynamic_sections (bfd * |
|
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 (strcmp (name, ".plt") == 0) |
if (CONST_STRNEQ (name, ".rela")) |
{ |
|
/* Remember whether there is a PLT. */ |
|
plt = s->size != 0; |
|
|
|
/* Correct for the number of res_N branches. */ |
|
if (plt && !bfd_link_pic (info)) |
|
{ |
|
htab->res_n_size = (s->size-28) / 3; |
|
s->size += htab->res_n_size; |
|
} |
|
} |
|
else if (CONST_STRNEQ (name, ".rela")) |
|
{ |
{ |
if (s->size != 0) |
if (s->size != 0) |
{ |
{ |
relocs = TRUE; |
if (s != htab->root.srelplt) |
|
relocs = TRUE; |
|
|
/* We use the reloc_count field as a counter if we need |
/* We use the reloc_count field as a counter if we need |
to copy relocs into the output file. */ |
to copy relocs into the output file. */ |
s->reloc_count = 0; |
s->reloc_count = 0; |
} |
} |
} |
} |
else if (CONST_STRNEQ (name, ".got")) |
else if (s == htab->root.splt) |
got = s->size != 0; |
{ |
else if (strcmp (name, ".dynbss") != 0) |
/* Correct for the number of res_N branches. */ |
|
if (s->size != 0 && !bfd_link_pic (info)) |
|
{ |
|
htab->res_n_size = (s->size - 28) / 3; |
|
s->size += htab->res_n_size; |
|
} |
|
} |
|
else if (s != htab->sbss |
|
&& s != htab->root.sgot |
|
&& s != htab->root.sgotplt |
|
&& s != htab->root.sdynbss |
|
&& s != htab->root.sdynrelro) |
/* It's not one of our sections, so don't allocate space. */ |
/* It's not one of our sections, so don't allocate space. */ |
continue; |
continue; |
|
|
if (s->size == 0) |
if (s->size == 0) |
{ |
{ |
/* If we don't need this section, strip it from the |
|
output file. This is mostly to handle .rela.bss and |
|
.rela.plt. We must create both sections in |
|
create_dynamic_sections, because they 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. */ |
|
s->flags |= SEC_EXCLUDE; |
s->flags |= SEC_EXCLUDE; |
continue; |
continue; |
} |
} |
Line 6046 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5880 nios2_elf32_size_dynamic_sections (bfd * |
|
continue; |
continue; |
|
|
/* Allocate memory for the section contents. */ |
/* Allocate memory for the section contents. */ |
/* FIXME: This should be a call to bfd_alloc not bfd_zalloc. |
|
Unused entries should be reclaimed before the section's contents |
|
are written out, but at the moment this does not happen. Thus in |
|
order to prevent writing out garbage, we initialize the section's |
|
contents to zero. */ |
|
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); |
if (s->contents == NULL) |
if (s->contents == NULL) |
return FALSE; |
return FALSE; |
Line 6061 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5890 nios2_elf32_size_dynamic_sections (bfd * |
|
if (htab->res_n_size) |
if (htab->res_n_size) |
elf_link_hash_traverse (& htab->root, adjust_dynrelocs, info); |
elf_link_hash_traverse (& htab->root, adjust_dynrelocs, info); |
|
|
if (elf_hash_table (info)->dynamic_sections_created) |
if (htab->root.dynamic_sections_created) |
{ |
{ |
/* Add some entries to the .dynamic section. We fill in the |
/* Add some entries to the .dynamic section. We fill in the |
values later, in elf_nios2_finish_dynamic_sections, but we |
values later, in elf_nios2_finish_dynamic_sections, but we |
Line 6074 nios2_elf32_size_dynamic_sections (bfd * |
|
Line 5903 nios2_elf32_size_dynamic_sections (bfd * |
|
if (!bfd_link_pic (info) && !add_dynamic_entry (DT_DEBUG, 0)) |
if (!bfd_link_pic (info) && !add_dynamic_entry (DT_DEBUG, 0)) |
return FALSE; |
return FALSE; |
|
|
if (got && !add_dynamic_entry (DT_PLTGOT, 0)) |
if (htab->root.sgotplt->size != 0 |
|
&& !add_dynamic_entry (DT_PLTGOT, 0)) |
return FALSE; |
return FALSE; |
|
|
if (plt |
if (htab->root.splt->size != 0 |
&& (!add_dynamic_entry (DT_PLTRELSZ, 0) |
&& (!add_dynamic_entry (DT_PLTRELSZ, 0) |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
|| !add_dynamic_entry (DT_JMPREL, 0))) |
|| !add_dynamic_entry (DT_JMPREL, 0))) |
Line 6184 nios2_elf_add_symbol_hook (bfd *abfd, |
|
Line 6014 nios2_elf_add_symbol_hook (bfd *abfd, |
|
asection **secp, |
asection **secp, |
bfd_vma *valp) |
bfd_vma *valp) |
{ |
{ |
bfd *dynobj; |
|
|
|
if (sym->st_shndx == SHN_COMMON |
if (sym->st_shndx == SHN_COMMON |
&& !bfd_link_relocatable (info) |
&& !bfd_link_relocatable (info) |
&& sym->st_size <= elf_gp_size (abfd) |
&& sym->st_size <= elf_gp_size (abfd) |
Line 6200 nios2_elf_add_symbol_hook (bfd *abfd, |
|
Line 6028 nios2_elf_add_symbol_hook (bfd *abfd, |
|
{ |
{ |
flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; |
flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; |
|
|
dynobj = elf_hash_table (info)->dynobj; |
if (htab->root.dynobj == NULL) |
if (!dynobj) |
htab->root.dynobj = abfd; |
dynobj = abfd; |
|
|
|
htab->sbss = bfd_make_section_anyway_with_flags (dynobj, ".sbss", |
htab->sbss = bfd_make_section_anyway_with_flags (htab->root.dynobj, |
flags); |
".sbss", flags); |
if (htab->sbss == NULL) |
if (htab->sbss == NULL) |
return FALSE; |
return FALSE; |
} |
} |
Line 6272 const struct bfd_elf_special_section elf |
|
Line 6099 const struct bfd_elf_special_section elf |
|
#define elf_backend_can_refcount 1 |
#define elf_backend_can_refcount 1 |
#define elf_backend_plt_readonly 1 |
#define elf_backend_plt_readonly 1 |
#define elf_backend_want_got_plt 1 |
#define elf_backend_want_got_plt 1 |
|
#define elf_backend_want_dynrelro 1 |
#define elf_backend_rela_normal 1 |
#define elf_backend_rela_normal 1 |
|
#define elf_backend_dtrel_excludes_plt 1 |
|
|
#define elf_backend_relocate_section nios2_elf32_relocate_section |
#define elf_backend_relocate_section nios2_elf32_relocate_section |
#define elf_backend_section_flags nios2_elf32_section_flags |
#define elf_backend_section_flags nios2_elf32_section_flags |
Line 6280 const struct bfd_elf_special_section elf |
|
Line 6109 const struct bfd_elf_special_section elf |
|
#define elf_backend_check_relocs nios2_elf32_check_relocs |
#define elf_backend_check_relocs nios2_elf32_check_relocs |
|
|
#define elf_backend_gc_mark_hook nios2_elf32_gc_mark_hook |
#define elf_backend_gc_mark_hook nios2_elf32_gc_mark_hook |
#define elf_backend_gc_sweep_hook nios2_elf32_gc_sweep_hook |
|
#define elf_backend_create_dynamic_sections \ |
#define elf_backend_create_dynamic_sections \ |
nios2_elf32_create_dynamic_sections |
nios2_elf32_create_dynamic_sections |
#define elf_backend_finish_dynamic_symbol nios2_elf32_finish_dynamic_symbol |
#define elf_backend_finish_dynamic_symbol nios2_elf32_finish_dynamic_symbol |