Index: bfd/elfxx-mips.c |
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c |
index f4935173fe1183f4306700a01185c21971a66848..9478f16380e89d0e451fda9d652177b712483fa6 100644 |
--- a/bfd/elfxx-mips.c |
+++ b/bfd/elfxx-mips.c |
@@ -1,6 +1,6 @@ |
/* MIPS-specific support for ELF |
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
- 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
Free Software Foundation, Inc. |
Most of the information added by Ian Lance Taylor, Cygnus Support, |
@@ -529,6 +529,13 @@ struct mips_htab_traverse_info |
|| r_type == R_MIPS_TLS_TPREL64 \ |
|| r_type == R_MIPS_TLS_TPREL_HI16 \ |
|| r_type == R_MIPS_TLS_TPREL_LO16 \ |
+ || r_type == R_MIPS16_TLS_GD \ |
+ || r_type == R_MIPS16_TLS_LDM \ |
+ || r_type == R_MIPS16_TLS_DTPREL_HI16 \ |
+ || r_type == R_MIPS16_TLS_DTPREL_LO16 \ |
+ || r_type == R_MIPS16_TLS_GOTTPREL \ |
+ || r_type == R_MIPS16_TLS_TPREL_HI16 \ |
+ || r_type == R_MIPS16_TLS_TPREL_LO16 \ |
|| r_type == R_MICROMIPS_TLS_GD \ |
|| r_type == R_MICROMIPS_TLS_LDM \ |
|| r_type == R_MICROMIPS_TLS_DTPREL_HI16 \ |
@@ -1453,14 +1460,17 @@ section_allows_mips16_refs_p (asection *section) |
function, or 0 if we can't decide which function that is. */ |
static unsigned long |
-mips16_stub_symndx (asection *sec ATTRIBUTE_UNUSED, |
+mips16_stub_symndx (const struct elf_backend_data *bed, |
+ asection *sec ATTRIBUTE_UNUSED, |
const Elf_Internal_Rela *relocs, |
const Elf_Internal_Rela *relend) |
{ |
+ int int_rels_per_ext_rel = bed->s->int_rels_per_ext_rel; |
const Elf_Internal_Rela *rel; |
- /* Trust the first R_MIPS_NONE relocation, if any. */ |
- for (rel = relocs; rel < relend; rel++) |
+ /* Trust the first R_MIPS_NONE relocation, if any, but not a subsequent |
+ one in a compound relocation. */ |
+ for (rel = relocs; rel < relend; rel += int_rels_per_ext_rel) |
if (ELF_R_TYPE (sec->owner, rel->r_info) == R_MIPS_NONE) |
return ELF_R_SYM (sec->owner, rel->r_info); |
@@ -1575,9 +1585,10 @@ _bfd_mips_elf_init_stubs (struct bfd_link_info *info, |
} |
/* Return true if H is a locally-defined PIC function, in the sense |
- that it might need $25 to be valid on entry. Note that MIPS16 |
- functions never need $25 to be valid on entry; they set up $gp |
- using PC-relative instructions instead. */ |
+ that it or its fn_stub might need $25 to be valid on entry. |
+ Note that MIPS16 functions set up $gp using PC-relative instructions, |
+ so they themselves never need $25 to be valid. Only non-MIPS16 |
+ entry points are of interest here. */ |
static bfd_boolean |
mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h) |
@@ -1586,11 +1597,32 @@ mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h) |
|| h->root.root.type == bfd_link_hash_defweak) |
&& h->root.def_regular |
&& !bfd_is_abs_section (h->root.root.u.def.section) |
- && !ELF_ST_IS_MIPS16 (h->root.other) |
+ && (!ELF_ST_IS_MIPS16 (h->root.other) |
+ || (h->fn_stub && h->need_fn_stub)) |
&& (PIC_OBJECT_P (h->root.root.u.def.section->owner) |
|| ELF_ST_IS_MIPS_PIC (h->root.other))); |
} |
+/* Set *SEC to the input section that contains the target of STUB. |
+ Return the offset of the target from the start of that section. */ |
+ |
+static bfd_vma |
+mips_elf_get_la25_target (struct mips_elf_la25_stub *stub, |
+ asection **sec) |
+{ |
+ if (ELF_ST_IS_MIPS16 (stub->h->root.other)) |
+ { |
+ BFD_ASSERT (stub->h->need_fn_stub); |
+ *sec = stub->h->fn_stub; |
+ return 0; |
+ } |
+ else |
+ { |
+ *sec = stub->h->root.root.u.def.section; |
+ return stub->h->root.root.u.def.value; |
+ } |
+} |
+ |
/* STUB describes an la25 stub that we have decided to implement |
by inserting an LUI/ADDIU pair before the target function. |
Create the section and redirect the function symbol to it. */ |
@@ -1615,7 +1647,7 @@ mips_elf_add_la25_intro (struct mips_elf_la25_stub *stub, |
sprintf (name, ".text.stub.%d", (int) htab_elements (htab->la25_stubs)); |
/* Create the section. */ |
- input_section = stub->h->root.root.u.def.section; |
+ mips_elf_get_la25_target (stub, &input_section); |
s = htab->add_stub_section (name, input_section, |
input_section->output_section); |
if (s == NULL) |
@@ -1689,12 +1721,6 @@ mips_elf_add_la25_stub (struct bfd_link_info *info, |
bfd_vma value; |
void **slot; |
- /* Prefer to use LUI/ADDIU stubs if the function is at the beginning |
- of the section and if we would need no more than 2 nops. */ |
- s = h->root.root.u.def.section; |
- value = h->root.root.u.def.value; |
- use_trampoline_p = (value != 0 || s->alignment_power > 4); |
- |
/* Describe the stub we want. */ |
search.stub_section = NULL; |
search.offset = 0; |
@@ -1724,6 +1750,11 @@ mips_elf_add_la25_stub (struct bfd_link_info *info, |
*stub = search; |
*slot = stub; |
+ /* Prefer to use LUI/ADDIU stubs if the function is at the beginning |
+ of the section and if we would need no more than 2 nops. */ |
+ value = mips_elf_get_la25_target (stub, &s); |
+ use_trampoline_p = (value != 0 || s->alignment_power > 4); |
+ |
h->la25_stub = stub; |
return (use_trampoline_p |
? mips_elf_add_la25_trampoline (stub, info) |
@@ -1864,6 +1895,13 @@ mips16_reloc_p (int r_type) |
case R_MIPS16_CALL16: |
case R_MIPS16_HI16: |
case R_MIPS16_LO16: |
+ case R_MIPS16_TLS_GD: |
+ case R_MIPS16_TLS_LDM: |
+ case R_MIPS16_TLS_DTPREL_HI16: |
+ case R_MIPS16_TLS_DTPREL_LO16: |
+ case R_MIPS16_TLS_GOTTPREL: |
+ case R_MIPS16_TLS_TPREL_HI16: |
+ case R_MIPS16_TLS_TPREL_LO16: |
return TRUE; |
default: |
@@ -1991,19 +2029,25 @@ micromips_branch_reloc_p (int r_type) |
static inline bfd_boolean |
tls_gd_reloc_p (unsigned int r_type) |
{ |
- return r_type == R_MIPS_TLS_GD || r_type == R_MICROMIPS_TLS_GD; |
+ return (r_type == R_MIPS_TLS_GD |
+ || r_type == R_MIPS16_TLS_GD |
+ || r_type == R_MICROMIPS_TLS_GD); |
} |
static inline bfd_boolean |
tls_ldm_reloc_p (unsigned int r_type) |
{ |
- return r_type == R_MIPS_TLS_LDM || r_type == R_MICROMIPS_TLS_LDM; |
+ return (r_type == R_MIPS_TLS_LDM |
+ || r_type == R_MIPS16_TLS_LDM |
+ || r_type == R_MICROMIPS_TLS_LDM); |
} |
static inline bfd_boolean |
tls_gottprel_reloc_p (unsigned int r_type) |
{ |
- return r_type == R_MIPS_TLS_GOTTPREL || r_type == R_MICROMIPS_TLS_GOTTPREL; |
+ return (r_type == R_MIPS_TLS_GOTTPREL |
+ || r_type == R_MIPS16_TLS_GOTTPREL |
+ || r_type == R_MICROMIPS_TLS_GOTTPREL); |
} |
void |
@@ -2816,16 +2860,16 @@ mips_elf_rel_dyn_section (struct bfd_link_info *info, bfd_boolean create_p) |
dname = MIPS_ELF_REL_DYN_NAME (info); |
dynobj = elf_hash_table (info)->dynobj; |
- sreloc = bfd_get_section_by_name (dynobj, dname); |
+ sreloc = bfd_get_linker_section (dynobj, dname); |
if (sreloc == NULL && create_p) |
{ |
- sreloc = bfd_make_section_with_flags (dynobj, dname, |
- (SEC_ALLOC |
- | SEC_LOAD |
- | SEC_HAS_CONTENTS |
- | SEC_IN_MEMORY |
- | SEC_LINKER_CREATED |
- | SEC_READONLY)); |
+ sreloc = bfd_make_section_anyway_with_flags (dynobj, dname, |
+ (SEC_ALLOC |
+ | SEC_LOAD |
+ | SEC_HAS_CONTENTS |
+ | SEC_IN_MEMORY |
+ | SEC_LINKER_CREATED |
+ | SEC_READONLY)); |
if (sreloc == NULL |
|| ! bfd_set_section_alignment (dynobj, sreloc, |
MIPS_ELF_LOG_FILE_ALIGN (dynobj))) |
@@ -4788,12 +4832,12 @@ mips_elf_create_compact_rel_section |
flagword flags; |
register asection *s; |
- if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL) |
+ if (bfd_get_linker_section (abfd, ".compact_rel") == NULL) |
{ |
flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED |
| SEC_READONLY); |
- s = bfd_make_section_with_flags (abfd, ".compact_rel", flags); |
+ s = bfd_make_section_anyway_with_flags (abfd, ".compact_rel", flags); |
if (s == NULL |
|| ! bfd_set_section_alignment (abfd, s, |
MIPS_ELF_LOG_FILE_ALIGN (abfd))) |
@@ -4830,7 +4874,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) |
/* We have to use an alignment of 2**4 here because this is hardcoded |
in the function stub generation and in the linker script. */ |
- s = bfd_make_section_with_flags (abfd, ".got", flags); |
+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); |
if (s == NULL |
|| ! bfd_set_section_alignment (abfd, s, 4)) |
return FALSE; |
@@ -4882,9 +4926,11 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) |
|= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL; |
/* We also need a .got.plt section when generating PLTs. */ |
- s = bfd_make_section_with_flags (abfd, ".got.plt", |
- SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS |
- | SEC_IN_MEMORY | SEC_LINKER_CREATED); |
+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", |
+ SEC_ALLOC | SEC_LOAD |
+ | SEC_HAS_CONTENTS |
+ | SEC_IN_MEMORY |
+ | SEC_LINKER_CREATED); |
if (s == NULL) |
return FALSE; |
htab->sgotplt = s; |
@@ -4911,7 +4957,8 @@ is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) |
stub. */ |
static bfd_boolean |
-mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type) |
+mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type, |
+ bfd_boolean target_is_16_bit_code_p) |
{ |
/* We specifically ignore branches and jumps from EF_PIC objects, |
where the onus is on the compiler or programmer to perform any |
@@ -4925,7 +4972,6 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type) |
{ |
case R_MIPS_26: |
case R_MIPS_PC16: |
- case R_MIPS16_26: |
case R_MICROMIPS_26_S1: |
case R_MICROMIPS_PC7_S1: |
case R_MICROMIPS_PC10_S1: |
@@ -4933,6 +4979,9 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type) |
case R_MICROMIPS_PC23_S2: |
return TRUE; |
+ case R_MIPS16_26: |
+ return !target_is_16_bit_code_p; |
+ |
default: |
return FALSE; |
} |
@@ -5193,14 +5242,28 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, |
have already noticed that we were going to need the |
stub. */ |
if (local_p) |
- sec = elf_tdata (input_bfd)->local_stubs[r_symndx]; |
+ { |
+ sec = elf_tdata (input_bfd)->local_stubs[r_symndx]; |
+ value = 0; |
+ } |
else |
{ |
BFD_ASSERT (h->need_fn_stub); |
- sec = h->fn_stub; |
+ if (h->la25_stub) |
+ { |
+ /* If a LA25 header for the stub itself exists, point to the |
+ prepended LUI/ADDIU sequence. */ |
+ sec = h->la25_stub->stub_section; |
+ value = h->la25_stub->offset; |
+ } |
+ else |
+ { |
+ sec = h->fn_stub; |
+ value = 0; |
+ } |
} |
- symbol = sec->output_section->vma + sec->output_offset; |
+ symbol = sec->output_section->vma + sec->output_offset + value; |
/* The target is 16-bit, but the stub isn't. */ |
target_is_16_bit_code_p = FALSE; |
} |
@@ -5250,7 +5313,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, |
/* If this is a direct call to a PIC function, redirect to the |
non-PIC stub. */ |
else if (h != NULL && h->la25_stub |
- && mips_elf_relocation_needs_la25_stub (input_bfd, r_type)) |
+ && mips_elf_relocation_needs_la25_stub (input_bfd, r_type, |
+ target_is_16_bit_code_p)) |
symbol = (h->la25_stub->stub_section->output_section->vma |
+ h->la25_stub->stub_section->output_offset |
+ h->la25_stub->offset); |
@@ -5322,6 +5386,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, |
case R_MIPS_TLS_GD: |
case R_MIPS_TLS_GOTTPREL: |
case R_MIPS_TLS_LDM: |
+ case R_MIPS16_TLS_GD: |
+ case R_MIPS16_TLS_GOTTPREL: |
+ case R_MIPS16_TLS_LDM: |
case R_MICROMIPS_TLS_GD: |
case R_MICROMIPS_TLS_GOTTPREL: |
case R_MICROMIPS_TLS_LDM: |
@@ -5491,6 +5558,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, |
break; |
case R_MIPS_TLS_DTPREL_HI16: |
+ case R_MIPS16_TLS_DTPREL_HI16: |
case R_MICROMIPS_TLS_DTPREL_HI16: |
value = (mips_elf_high (addend + symbol - dtprel_base (info)) |
& howto->dst_mask); |
@@ -5499,17 +5567,22 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, |
case R_MIPS_TLS_DTPREL_LO16: |
case R_MIPS_TLS_DTPREL32: |
case R_MIPS_TLS_DTPREL64: |
+ case R_MIPS16_TLS_DTPREL_LO16: |
case R_MICROMIPS_TLS_DTPREL_LO16: |
value = (symbol + addend - dtprel_base (info)) & howto->dst_mask; |
break; |
case R_MIPS_TLS_TPREL_HI16: |
+ case R_MIPS16_TLS_TPREL_HI16: |
case R_MICROMIPS_TLS_TPREL_HI16: |
value = (mips_elf_high (addend + symbol - tprel_base (info)) |
& howto->dst_mask); |
break; |
case R_MIPS_TLS_TPREL_LO16: |
+ case R_MIPS_TLS_TPREL32: |
+ case R_MIPS_TLS_TPREL64: |
+ case R_MIPS16_TLS_TPREL_LO16: |
case R_MICROMIPS_TLS_TPREL_LO16: |
value = (symbol + addend - tprel_base (info)) & howto->dst_mask; |
break; |
@@ -5642,6 +5715,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, |
case R_MIPS_TLS_GOTTPREL: |
case R_MIPS_TLS_LDM: |
case R_MIPS_GOT_DISP: |
+ case R_MIPS16_TLS_GD: |
+ case R_MIPS16_TLS_GOTTPREL: |
+ case R_MIPS16_TLS_LDM: |
case R_MICROMIPS_TLS_GD: |
case R_MICROMIPS_TLS_GOTTPREL: |
case R_MICROMIPS_TLS_LDM: |
@@ -6104,7 +6180,7 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd, |
/* On IRIX5, make an entry of compact relocation info. */ |
if (IRIX_COMPAT (output_bfd) == ict_irix5) |
{ |
- asection *scpt = bfd_get_section_by_name (dynobj, ".compact_rel"); |
+ asection *scpt = bfd_get_linker_section (dynobj, ".compact_rel"); |
bfd_byte *cr; |
if (scpt) |
@@ -7146,7 +7222,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
EABI doesn't. */ |
if (!htab->is_vxworks) |
{ |
- s = bfd_get_section_by_name (abfd, ".dynamic"); |
+ s = bfd_get_linker_section (abfd, ".dynamic"); |
if (s != NULL) |
{ |
if (! bfd_set_section_flags (abfd, s, flags)) |
@@ -7162,9 +7238,9 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
return FALSE; |
/* Create .stub section. */ |
- s = bfd_make_section_with_flags (abfd, |
- MIPS_ELF_STUB_SECTION_NAME (abfd), |
- flags | SEC_CODE); |
+ s = bfd_make_section_anyway_with_flags (abfd, |
+ MIPS_ELF_STUB_SECTION_NAME (abfd), |
+ flags | SEC_CODE); |
if (s == NULL |
|| ! bfd_set_section_alignment (abfd, s, |
MIPS_ELF_LOG_FILE_ALIGN (abfd))) |
@@ -7173,10 +7249,10 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
if ((IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none) |
&& !info->shared |
- && bfd_get_section_by_name (abfd, ".rld_map") == NULL) |
+ && bfd_get_linker_section (abfd, ".rld_map") == NULL) |
{ |
- s = bfd_make_section_with_flags (abfd, ".rld_map", |
- flags &~ (flagword) SEC_READONLY); |
+ s = bfd_make_section_anyway_with_flags (abfd, ".rld_map", |
+ flags &~ (flagword) SEC_READONLY); |
if (s == NULL |
|| ! bfd_set_section_alignment (abfd, s, |
MIPS_ELF_LOG_FILE_ALIGN (abfd))) |
@@ -7214,19 +7290,20 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
} |
/* Change alignments of some sections. */ |
- s = bfd_get_section_by_name (abfd, ".hash"); |
+ s = bfd_get_linker_section (abfd, ".hash"); |
if (s != NULL) |
bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)); |
- s = bfd_get_section_by_name (abfd, ".dynsym"); |
+ s = bfd_get_linker_section (abfd, ".dynsym"); |
if (s != NULL) |
bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)); |
- s = bfd_get_section_by_name (abfd, ".dynstr"); |
+ s = bfd_get_linker_section (abfd, ".dynstr"); |
if (s != NULL) |
bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)); |
+ /* ??? */ |
s = bfd_get_section_by_name (abfd, ".reginfo"); |
if (s != NULL) |
bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)); |
- s = bfd_get_section_by_name (abfd, ".dynamic"); |
+ s = bfd_get_linker_section (abfd, ".dynamic"); |
if (s != NULL) |
bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)); |
} |
@@ -7256,7 +7333,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
and is filled in by the rtld to contain a pointer to |
the _r_debug structure. Its symbol value will be set in |
_bfd_mips_elf_finish_dynamic_symbol. */ |
- s = bfd_get_section_by_name (abfd, ".rld_map"); |
+ s = bfd_get_linker_section (abfd, ".rld_map"); |
BFD_ASSERT (s != NULL); |
name = SGI_COMPAT (abfd) ? "__rld_map" : "__RLD_MAP"; |
@@ -7283,15 +7360,15 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
return FALSE; |
/* Cache the sections created above. */ |
- htab->splt = bfd_get_section_by_name (abfd, ".plt"); |
- htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss"); |
+ htab->splt = bfd_get_linker_section (abfd, ".plt"); |
+ htab->sdynbss = bfd_get_linker_section (abfd, ".dynbss"); |
if (htab->is_vxworks) |
{ |
- htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss"); |
- htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt"); |
+ htab->srelbss = bfd_get_linker_section (abfd, ".rela.bss"); |
+ htab->srelplt = bfd_get_linker_section (abfd, ".rela.plt"); |
} |
else |
- htab->srelplt = bfd_get_section_by_name (abfd, ".rel.plt"); |
+ htab->srelplt = bfd_get_linker_section (abfd, ".rel.plt"); |
if (!htab->sdynbss |
|| (htab->is_vxworks && !htab->srelbss && !info->shared) |
|| !htab->srelplt |
@@ -7498,7 +7575,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
/* Look at the relocation information to figure out which symbol |
this is for. */ |
- r_symndx = mips16_stub_symndx (sec, relocs, rel_end); |
+ r_symndx = mips16_stub_symndx (bed, sec, relocs, rel_end); |
if (r_symndx == 0) |
{ |
(*_bfd_error_handler) |
@@ -7623,7 +7700,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
/* Look at the relocation information to figure out which symbol |
this is for. */ |
- r_symndx = mips16_stub_symndx (sec, relocs, rel_end); |
+ r_symndx = mips16_stub_symndx (bed, sec, relocs, rel_end); |
if (r_symndx == 0) |
{ |
(*_bfd_error_handler) |
@@ -7775,8 +7852,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
can_make_dynamic_p = FALSE; |
switch (r_type) |
{ |
- case R_MIPS16_GOT16: |
- case R_MIPS16_CALL16: |
case R_MIPS_GOT16: |
case R_MIPS_CALL16: |
case R_MIPS_CALL_HI16: |
@@ -7789,6 +7864,11 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
case R_MIPS_TLS_GOTTPREL: |
case R_MIPS_TLS_GD: |
case R_MIPS_TLS_LDM: |
+ case R_MIPS16_GOT16: |
+ case R_MIPS16_CALL16: |
+ case R_MIPS16_TLS_GOTTPREL: |
+ case R_MIPS16_TLS_GD: |
+ case R_MIPS16_TLS_LDM: |
case R_MICROMIPS_GOT16: |
case R_MICROMIPS_CALL16: |
case R_MICROMIPS_CALL_HI16: |
@@ -7926,7 +8006,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
return FALSE; |
} |
- if (h != NULL && mips_elf_relocation_needs_la25_stub (abfd, r_type)) |
+ if (h != NULL |
+ && mips_elf_relocation_needs_la25_stub (abfd, r_type, |
+ ELF_ST_IS_MIPS16 (h->other))) |
((struct mips_elf_link_hash_entry *) h)->has_nonpic_branches = TRUE; |
switch (r_type) |
@@ -8023,12 +8105,14 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
break; |
case R_MIPS_TLS_GOTTPREL: |
+ case R_MIPS16_TLS_GOTTPREL: |
case R_MICROMIPS_TLS_GOTTPREL: |
if (info->shared) |
info->flags |= DF_STATIC_TLS; |
/* Fall through */ |
case R_MIPS_TLS_LDM: |
+ case R_MIPS16_TLS_LDM: |
case R_MICROMIPS_TLS_LDM: |
if (tls_ldm_reloc_p (r_type)) |
{ |
@@ -8038,6 +8122,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, |
/* Fall through */ |
case R_MIPS_TLS_GD: |
+ case R_MIPS16_TLS_GD: |
case R_MICROMIPS_TLS_GD: |
/* This symbol requires a global offset table entry, or two |
for TLS GD relocations. */ |
@@ -8583,7 +8668,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, |
/* On non-VxWorks targets, the first two entries in .got.plt |
are reserved. */ |
if (!htab->is_vxworks) |
- htab->sgotplt->size += 2 * MIPS_ELF_GOT_SIZE (dynobj); |
+ htab->sgotplt->size |
+ += get_elf_backend_data (dynobj)->got_header_size; |
/* On VxWorks, also allocate room for the header's |
.rela.plt.unloaded entries. */ |
@@ -8944,7 +9030,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, |
/* Set the contents of the .interp section to the interpreter. */ |
if (info->executable) |
{ |
- s = bfd_get_section_by_name (dynobj, ".interp"); |
+ s = bfd_get_linker_section (dynobj, ".interp"); |
BFD_ASSERT (s != NULL); |
s->size |
= strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1; |
@@ -8969,7 +9055,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, |
} |
/* Allocate space for global sym dynamic relocs. */ |
- elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info); |
+ elf_link_hash_traverse (&htab->root, allocate_dynrelocs, info); |
mips_elf_estimate_stub_size (output_bfd, info); |
@@ -9242,6 +9328,55 @@ mips_elf_adjust_addend (bfd *output_bfd, struct bfd_link_info *info, |
} |
} |
+/* Handle relocations against symbols from removed linkonce sections, |
+ or sections discarded by a linker script. We use this wrapper around |
+ RELOC_AGAINST_DISCARDED_SECTION to handle triplets of compound relocs |
+ on 64-bit ELF targets. In this case for any relocation handled, which |
+ always be the first in a triplet, the remaining two have to be processed |
+ together with the first, even if they are R_MIPS_NONE. It is the symbol |
+ index referred by the first reloc that applies to all the three and the |
+ remaining two never refer to an object symbol. And it is the final |
+ relocation (the last non-null one) that determines the output field of |
+ the whole relocation so retrieve the corresponding howto structure for |
+ the relocatable field to be cleared by RELOC_AGAINST_DISCARDED_SECTION. |
+ |
+ Note that RELOC_AGAINST_DISCARDED_SECTION is a macro that uses "continue" |
+ and therefore requires to be pasted in a loop. It also defines a block |
+ and does not protect any of its arguments, hence the extra brackets. */ |
+ |
+static void |
+mips_reloc_against_discarded_section (bfd *output_bfd, |
+ struct bfd_link_info *info, |
+ bfd *input_bfd, asection *input_section, |
+ Elf_Internal_Rela **rel, |
+ const Elf_Internal_Rela **relend, |
+ bfd_boolean rel_reloc, |
+ reloc_howto_type *howto, |
+ bfd_byte *contents) |
+{ |
+ const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); |
+ int count = bed->s->int_rels_per_ext_rel; |
+ unsigned int r_type; |
+ int i; |
+ |
+ for (i = count - 1; i > 0; i--) |
+ { |
+ r_type = ELF_R_TYPE (output_bfd, (*rel)[i].r_info); |
+ if (r_type != R_MIPS_NONE) |
+ { |
+ howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type, !rel_reloc); |
+ break; |
+ } |
+ } |
+ do |
+ { |
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, |
+ (*rel), count, (*relend), |
+ howto, i, contents); |
+ } |
+ while (0); |
+} |
+ |
/* Relocate a MIPS ELF section. */ |
bfd_boolean |
@@ -9307,9 +9442,13 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, |
sec = h->root.u.def.section; |
} |
- if (sec != NULL && elf_discarded_section (sec)) |
- RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, |
- rel, relend, howto, contents); |
+ if (sec != NULL && discarded_section (sec)) |
+ { |
+ mips_reloc_against_discarded_section (output_bfd, info, input_bfd, |
+ input_section, &rel, &relend, |
+ rel_reloc, howto, contents); |
+ continue; |
+ } |
if (r_type == R_MIPS_64 && ! NEWABI_P (input_bfd)) |
{ |
@@ -9623,9 +9762,9 @@ mips_elf_create_la25_stub (void **slot, void *data) |
offset = stub->offset; |
/* Work out the target address. */ |
- target = (stub->h->root.root.u.def.section->output_section->vma |
- + stub->h->root.root.u.def.section->output_offset |
- + stub->h->root.root.u.def.value); |
+ target = mips_elf_get_la25_target (stub, &s); |
+ target += s->output_section->vma + s->output_offset; |
+ |
target_high = ((target + 0x8000) >> 16) & 0xffff; |
target_low = (target & 0xffff); |
@@ -10374,7 +10513,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, |
dynobj = elf_hash_table (info)->dynobj; |
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); |
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic"); |
sgot = htab->sgot; |
gg = htab->got_info; |
@@ -10720,7 +10859,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, |
if (SGI_COMPAT (output_bfd)) |
{ |
/* Write .compact_rel section out. */ |
- s = bfd_get_section_by_name (dynobj, ".compact_rel"); |
+ s = bfd_get_linker_section (dynobj, ".compact_rel"); |
if (s != NULL) |
{ |
cpt.id1 = 1; |
@@ -12325,7 +12464,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, |
/* Get a copy of the native relocations. */ |
internal_relocs = (_bfd_elf_link_read_relocs |
- (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, |
+ (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, |
link_info->keep_memory)); |
if (internal_relocs == NULL) |
goto error_return; |
@@ -13172,15 +13311,15 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) |
if (SGI_COMPAT (abfd) && info->shared) |
{ |
/* Create .rtproc section. */ |
- rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc"); |
+ rtproc_sec = bfd_get_linker_section (abfd, ".rtproc"); |
if (rtproc_sec == NULL) |
{ |
flagword flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY |
| SEC_LINKER_CREATED | SEC_READONLY); |
- rtproc_sec = bfd_make_section_with_flags (abfd, |
- ".rtproc", |
- flags); |
+ rtproc_sec = bfd_make_section_anyway_with_flags (abfd, |
+ ".rtproc", |
+ flags); |
if (rtproc_sec == NULL |
|| ! bfd_set_section_alignment (abfd, rtproc_sec, 4)) |
return FALSE; |