| 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;
|
|
|