X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-mips.c;h=6dd0592917dbfd67c7d52c4ac805d8d168cb6202;hb=fd885f3a4d85dc33d794ca359ea91f31e3082717;hp=36b881ec93a099de5bfe43a6d580e55a4261db0e;hpb=2309ddf22209e1d2ab769dc778d9f764463b8509;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 36b881ec93..6dd0592917 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, @@ -436,8 +436,8 @@ struct mips_elf_link_hash_table entry is set to the address of __rld_obj_head as in IRIX5. */ bfd_boolean use_rld_obj_head; - /* This is the value of the __rld_map or __rld_obj_head symbol. */ - bfd_vma rld_value; + /* The __rld_map or __rld_obj_head symbol. */ + struct elf_link_hash_entry *rld_symbol; /* This is set if we see any mips16 stub sections. */ bfd_boolean mips16_stubs_seen; @@ -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 \ @@ -768,6 +775,10 @@ static bfd *reldyn_sorting_bfd; #define MIPS_ELF_GOT_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->arch_size / 8) +/* The size of the .rld_map section. */ +#define MIPS_ELF_RLD_MAP_SIZE(abfd) \ + (get_elf_backend_data (abfd)->s->arch_size / 8) + /* The size of a symbol-table entry. */ #define MIPS_ELF_SYM_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->sizeof_sym) @@ -917,7 +928,7 @@ static const bfd_vma mips_o32_exec_plt0_entry[] = 0x8f990000, /* lw $25, %lo(&GOTPLT[0])($28) */ 0x279c0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */ 0x031cc023, /* subu $24, $24, $28 */ - 0x03e07821, /* move $15, $31 */ + 0x03e07821, /* move $15, $31 # 32-bit move (addu) */ 0x0018c082, /* srl $24, $24, 2 */ 0x0320f809, /* jalr $25 */ 0x2718fffe /* subu $24, $24, 2 */ @@ -931,7 +942,7 @@ static const bfd_vma mips_n32_exec_plt0_entry[] = 0x8dd90000, /* lw $25, %lo(&GOTPLT[0])($14) */ 0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */ 0x030ec023, /* subu $24, $24, $14 */ - 0x03e07821, /* move $15, $31 */ + 0x03e07821, /* move $15, $31 # 32-bit move (addu) */ 0x0018c082, /* srl $24, $24, 2 */ 0x0320f809, /* jalr $25 */ 0x2718fffe /* subu $24, $24, 2 */ @@ -945,7 +956,7 @@ static const bfd_vma mips_n64_exec_plt0_entry[] = 0xddd90000, /* ld $25, %lo(&GOTPLT[0])($14) */ 0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */ 0x030ec023, /* subu $24, $24, $14 */ - 0x03e07821, /* move $15, $31 */ + 0x03e0782d, /* move $15, $31 # 64-bit move (daddu) */ 0x0018c0c2, /* srl $24, $24, 3 */ 0x0320f809, /* jalr $25 */ 0x2718fffe /* subu $24, $24, 2 */ @@ -1449,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); @@ -1571,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) @@ -1582,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. */ @@ -1611,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) @@ -1685,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; @@ -1720,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) @@ -1860,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: @@ -1987,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 @@ -4907,7 +4955,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 @@ -4921,7 +4970,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: @@ -4929,6 +4977,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; } @@ -5189,14 +5240,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; } @@ -5246,7 +5311,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); @@ -5318,6 +5384,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: @@ -5487,6 +5556,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); @@ -5495,17 +5565,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; @@ -5527,10 +5602,11 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, 12: addu $v0,$v1 14: move $gp,$v0 So the offsets of hi and lo relocs are the same, but the - $pc is four higher than $t9 would be, so reduce - both reloc addends by 4. */ + base $pc is that used by the ADDIUPC instruction at $t9 + 4. + ADDIUPC clears the low two bits of the instruction address, + so the base is ($t9 + 4) & ~3. */ if (r_type == R_MIPS16_HI16) - value = mips_elf_high (addend + gp - p - 4); + value = mips_elf_high (addend + gp - ((p + 4) & ~(bfd_vma) 0x3)); /* The microMIPS .cpload sequence uses the same assembly instructions as the traditional psABI version, but the incoming $t9 has the low bit set. */ @@ -5553,7 +5629,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* See the comment for R_MIPS16_HI16 above for the reason for this conditional. */ if (r_type == R_MIPS16_LO16) - value = addend + gp - p; + value = addend + gp - (p & ~(bfd_vma) 0x3); else if (r_type == R_MICROMIPS_LO16 || r_type == R_MICROMIPS_HI0_LO16) value = addend + gp - p + 3; @@ -5637,6 +5713,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: @@ -6182,6 +6261,9 @@ _bfd_elf_mips_mach (flagword flags) case E_MIPS_MACH_LS3A: return bfd_mach_mips_loongson_3a; + case E_MIPS_MACH_OCTEON2: + return bfd_mach_mips_octeon2; + case E_MIPS_MACH_OCTEON: return bfd_mach_mips_octeon; @@ -6337,7 +6419,6 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym) { asection *section = bfd_get_section_by_name (abfd, ".text"); - BFD_ASSERT (SGI_COMPAT (abfd)); if (section != NULL) { asym->section = section; @@ -6353,7 +6434,6 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym) { asection *section = bfd_get_section_by_name (abfd, ".data"); - BFD_ASSERT (SGI_COMPAT (abfd)); if (section != NULL) { asym->section = section; @@ -7081,6 +7161,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, return FALSE; mips_elf_hash_table (info)->use_rld_obj_head = TRUE; + mips_elf_hash_table (info)->rld_symbol = h; } /* If this is a mips16 text symbol, add 1 to the value to make it @@ -7266,6 +7347,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; + mips_elf_hash_table (info)->rld_symbol = h; } } @@ -7490,7 +7572,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) @@ -7615,7 +7697,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) @@ -7767,8 +7849,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: @@ -7781,6 +7861,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: @@ -7918,7 +8003,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) @@ -8015,12 +8102,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)) { @@ -8030,6 +8119,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. */ @@ -9027,7 +9117,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, { /* We add a room for __rld_map. It will be filled in by the rtld to contain a pointer to the _r_debug structure. */ - s->size += 4; + s->size += MIPS_ELF_RLD_MAP_SIZE (output_bfd); } else if (SGI_COMPAT (output_bfd) && CONST_STRNEQ (name, ".compact_rel")) @@ -9234,6 +9324,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 @@ -9299,9 +9438,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)) { @@ -9615,9 +9758,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); @@ -10030,31 +10173,6 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, if (IRIX_COMPAT (output_bfd) == ict_irix6) mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym); - if (! info->shared) - { - if (! mips_elf_hash_table (info)->use_rld_obj_head - && (strcmp (name, "__rld_map") == 0 - || strcmp (name, "__RLD_MAP") == 0)) - { - asection *s = bfd_get_section_by_name (dynobj, ".rld_map"); - BFD_ASSERT (s != NULL); - sym->st_value = s->output_section->vma + s->output_offset; - bfd_put_32 (output_bfd, 0, s->contents); - if (mips_elf_hash_table (info)->rld_value == 0) - mips_elf_hash_table (info)->rld_value = sym->st_value; - } - else if (mips_elf_hash_table (info)->use_rld_obj_head - && strcmp (name, "__rld_obj_head") == 0) - { - /* IRIX6 does not use a .rld_map section. */ - if (IRIX_COMPAT (output_bfd) == ict_irix5 - || IRIX_COMPAT (output_bfd) == ict_none) - BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map") - != NULL); - mips_elf_hash_table (info)->rld_value = sym->st_value; - } - } - /* Keep dynamic MIPS16 symbols odd. This allows the dynamic linker to treat MIPS16 symbols like any other. */ if (ELF_ST_IS_MIPS16 (sym->st_other)) @@ -10517,7 +10635,19 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, break; case DT_MIPS_RLD_MAP: - dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value; + { + struct elf_link_hash_entry *h; + h = mips_elf_hash_table (info)->rld_symbol; + if (!h) + { + dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj); + swap_out_p = FALSE; + break; + } + s = h->root.u.def.section; + dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset + + h->root.u.def.value); + } break; case DT_MIPS_OPTIONS: @@ -10887,6 +11017,7 @@ mips_set_isa_flags (bfd *abfd) break; case bfd_mach_mips_octeon: + case bfd_mach_mips_octeonp: val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON; break; @@ -10894,6 +11025,10 @@ mips_set_isa_flags (bfd *abfd) val = E_MIPS_ARCH_64 | E_MIPS_MACH_XLR; break; + case bfd_mach_mips_octeon2: + val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON2; + break; + case bfd_mach_mipsisa32: val = E_MIPS_ARCH_32; break; @@ -11567,7 +11702,8 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section, line_ptr)) return TRUE; - if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, + section, symbols, offset, filename_ptr, functionname_ptr, line_ptr, ABI_64_P (abfd) ? 8 : 0, &elf_tdata (abfd)->dwarf2_find_line_info)) @@ -11987,7 +12123,7 @@ static const struct opcode_descriptor b_insn_16 = { /* "b", "mD", */ 0xcc00, 0xfc00 }; static const struct opcode_descriptor bz_insn_16 = - { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xac00 }; + { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00 }; /* 32-bit and 16-bit branch EQ and NE zero. */ @@ -12239,7 +12375,7 @@ check_br16 (bfd *abfd, bfd_byte *ptr, unsigned long reg) /* If PTR points to a 32-bit branch or jump that doesn't fiddle with REG, then return TRUE, otherwise FALSE. */ -static int +static bfd_boolean check_br32 (bfd *abfd, bfd_byte *ptr, unsigned long reg) { unsigned long opcode; @@ -12264,32 +12400,37 @@ check_br32 (bfd *abfd, bfd_byte *ptr, unsigned long reg) return FALSE; } -/* Bitsize checking. */ -#define IS_BITSIZE(val, N) \ - (((((val) & ((1ULL << (N)) - 1)) ^ (1ULL << ((N) - 1))) \ - - (1ULL << ((N) - 1))) == (val)) - -/* See if relocations [INTERNAL_RELOCS, IRELEND) confirm that there - is a 4-byte branch at offset OFFSET. */ +/* If the instruction encoding at PTR and relocations [INTERNAL_RELOCS, + IRELEND) at OFFSET indicate that there must be a compact branch there, + then return TRUE, otherwise FALSE. */ static bfd_boolean -check_4byte_branch (Elf_Internal_Rela *internal_relocs, - Elf_Internal_Rela *irelend, bfd_vma offset) +check_relocated_bzc (bfd *abfd, const bfd_byte *ptr, bfd_vma offset, + const Elf_Internal_Rela *internal_relocs, + const Elf_Internal_Rela *irelend) { - Elf_Internal_Rela *irel; - unsigned long r_type; + const Elf_Internal_Rela *irel; + unsigned long opcode; + + opcode = bfd_get_16 (abfd, ptr); + opcode <<= 16; + opcode |= bfd_get_16 (abfd, ptr + 2); + if (find_match (opcode, bzc_insns_32) < 0) + return FALSE; for (irel = internal_relocs; irel < irelend; irel++) - if (irel->r_offset == offset) - { - r_type = ELF32_R_TYPE (irel->r_info); - if (r_type == R_MICROMIPS_26_S1 - || r_type == R_MICROMIPS_PC16_S1 - || r_type == R_MICROMIPS_JALR) - return TRUE; - } + if (irel->r_offset == offset + && ELF32_R_TYPE (irel->r_info) == R_MICROMIPS_PC16_S1) + return TRUE; + return FALSE; } + +/* Bitsize checking. */ +#define IS_BITSIZE(val, N) \ + (((((val) & ((1ULL << (N)) - 1)) ^ (1ULL << ((N) - 1))) \ + - (1ULL << ((N) - 1))) == (val)) + bfd_boolean _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, @@ -12451,6 +12592,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, out the offset). */ if (r_type == R_MICROMIPS_HI16 && MATCH (opcode, lui_insn)) { + bfd_boolean bzc = FALSE; unsigned long nextopc; unsigned long reg; bfd_vma offset; @@ -12474,18 +12616,19 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, && ELF32_R_SYM (irel[2].r_info) == r_symndx) continue; - /* See if the LUI instruction *might* be in a branch delay slot. */ + /* See if the LUI instruction *might* be in a branch delay slot. + We check whether what looks like a 16-bit branch or jump is + actually an immediate argument to a compact branch, and let + it through if so. */ if (irel->r_offset >= 2 && check_br16_dslot (abfd, ptr - 2) && !(irel->r_offset >= 4 - /* If the instruction is actually a 4-byte branch, - the value of check_br16_dslot doesn't matter. - We should use check_br32_dslot to check whether - the branch has a delay slot. */ - && check_4byte_branch (internal_relocs, irelend, - irel->r_offset - 4))) + && (bzc = check_relocated_bzc (abfd, + ptr - 4, irel->r_offset - 4, + internal_relocs, irelend)))) continue; if (irel->r_offset >= 4 + && !bzc && check_br32_dslot (abfd, ptr - 4)) continue; @@ -12787,7 +12930,7 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd) ret->procedure_count = 0; ret->compact_rel_size = 0; ret->use_rld_obj_head = FALSE; - ret->rld_value = 0; + ret->rld_symbol = NULL; ret->mips16_stubs_seen = FALSE; ret->use_plts_and_copy_relocs = FALSE; ret->is_vxworks = FALSE; @@ -13485,6 +13628,8 @@ struct mips_mach_extension { static const struct mips_mach_extension mips_mach_extensions[] = { /* MIPS64r2 extensions. */ + { bfd_mach_mips_octeon2, bfd_mach_mips_octeonp }, + { bfd_mach_mips_octeonp, bfd_mach_mips_octeon }, { bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 }, /* MIPS64 extensions. */