X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-mips.c;h=211f6f9c7e81243885c638b7d470e65de2ba3c99;hb=f2b740ac53a3347b7e0fe1a09e52f6311265e709;hp=89d4409b097ed1b014bea0b637aa67da3aeb2afc;hpb=28d45e28be904a53fef4310b3d41e41b045885b0;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 89d4409b09..211f6f9c7e 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -1,5 +1,5 @@ /* MIPS-specific support for ELF - Copyright (C) 1993-2016 Free Software Foundation, Inc. + Copyright (C) 1993-2018 Free Software Foundation, Inc. Most of the information added by Ian Lance Taylor, Cygnus Support, . @@ -310,14 +310,17 @@ struct mips_elf_hash_sort_data struct elf_link_hash_entry *low; /* The least dynamic symbol table index corresponding to a non-TLS symbol with a GOT entry. */ - long min_got_dynindx; + bfd_size_type min_got_dynindx; /* The greatest dynamic symbol table index corresponding to a symbol with a GOT entry that is not referenced (e.g., a dynamic symbol with dynamic relocations pointing to it from non-primary GOTs). */ - long max_unref_got_dynindx; - /* The greatest dynamic symbol table index not corresponding to a + bfd_size_type max_unref_got_dynindx; + /* The greatest dynamic symbol table index corresponding to a local + symbol. */ + bfd_size_type max_local_dynindx; + /* The greatest dynamic symbol table index corresponding to an external symbol without a GOT entry. */ - long max_non_got_dynindx; + bfd_size_type max_non_got_dynindx; }; /* We make up to two PLT entries if needed, one for standard MIPS code @@ -443,6 +446,9 @@ struct mips_elf_link_hash_table /* True if we can only use 32-bit microMIPS instructions. */ bfd_boolean insn32; + /* True if we suppress checks for invalid branches between ISA modes. */ + bfd_boolean ignore_branch_isa; + /* True if we're generating code for VxWorks. */ bfd_boolean is_vxworks; @@ -451,14 +457,8 @@ struct mips_elf_link_hash_table /* Shortcuts to some dynamic sections, or NULL if they are not being used. */ - asection *srelbss; - asection *sdynbss; - asection *srelplt; asection *srelplt2; - asection *sgotplt; - asection *splt; asection *sstubs; - asection *sgot; /* The master GOT information. */ struct mips_got_info *got_info; @@ -868,8 +868,8 @@ static bfd *reldyn_sorting_bfd; /* Put out word-sized data. */ #define MIPS_ELF_PUT_WORD(abfd, val, ptr) \ - (ABI_64_P (abfd) \ - ? bfd_put_64 (abfd, val, ptr) \ + (ABI_64_P (abfd) \ + ? bfd_put_64 (abfd, val, ptr) \ : bfd_put_32 (abfd, val, ptr)) /* The opcode for word-sized loads (LW or LD). */ @@ -910,10 +910,10 @@ static bfd *reldyn_sorting_bfd; #define STUB_LW(abfd) \ ((ABI_64_P (abfd) \ ? 0xdf998010 /* ld t9,0x8010(gp) */ \ - : 0x8f998010)) /* lw t9,0x8010(gp) */ + : 0x8f998010)) /* lw t9,0x8010(gp) */ #define STUB_MOVE 0x03e07825 /* or t7,ra,zero */ #define STUB_LUI(VAL) (0x3c180000 + (VAL)) /* lui t8,VAL */ -#define STUB_JALR 0x0320f809 /* jalr t9,ra */ +#define STUB_JALR 0x0320f809 /* jalr ra,t9 */ #define STUB_ORI(VAL) (0x37180000 + (VAL)) /* ori t8,t8,VAL */ #define STUB_LI16U(VAL) (0x34180000 + (VAL)) /* ori t8,zero,VAL unsigned */ #define STUB_LI16S(abfd, VAL) \ @@ -951,9 +951,9 @@ static bfd *reldyn_sorting_bfd; /* The name of the dynamic interpreter. This is put in the .interp section. */ -#define ELF_DYNAMIC_INTERPRETER(abfd) \ - (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" \ - : ABI_64_P (abfd) ? "/usr/lib64/libc.so.1" \ +#define ELF_DYNAMIC_INTERPRETER(abfd) \ + (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" \ + : ABI_64_P (abfd) ? "/usr/lib64/libc.so.1" \ : "/usr/lib/libc.so.1") #ifdef BFD64 @@ -1192,7 +1192,7 @@ static void bfd_put_micromips_32 (const bfd *abfd, bfd_vma opcode, bfd_byte *ptr) { bfd_put_16 (abfd, (opcode >> 16) & 0xffff, ptr); - bfd_put_16 (abfd, opcode & 0xffff, ptr + 2); + bfd_put_16 (abfd, opcode & 0xffff, ptr + 2); } /* microMIPS 32-bit opcode helper retriever. */ @@ -1578,19 +1578,23 @@ mips_elf_create_stub_symbol (struct bfd_link_info *info, const char *prefix, asection *s, bfd_vma value, bfd_vma size) { + bfd_boolean micromips_p = ELF_ST_IS_MICROMIPS (h->root.other); struct bfd_link_hash_entry *bh; struct elf_link_hash_entry *elfh; - const char *name; + char *name; + bfd_boolean res; - if (ELF_ST_IS_MICROMIPS (h->root.other)) + if (micromips_p) value |= 1; /* Create a new symbol. */ - name = ACONCAT ((prefix, h->root.root.root.string, NULL)); + name = concat (prefix, h->root.root.root.string, NULL); bh = NULL; - if (!_bfd_generic_link_add_one_symbol (info, s->owner, name, - BSF_LOCAL, s, value, NULL, - TRUE, FALSE, &bh)) + res = _bfd_generic_link_add_one_symbol (info, s->owner, name, + BSF_LOCAL, s, value, NULL, + TRUE, FALSE, &bh); + free (name); + if (! res) return FALSE; /* Make it a local function. */ @@ -1598,6 +1602,8 @@ mips_elf_create_stub_symbol (struct bfd_link_info *info, elfh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC); elfh->size = size; elfh->forced_local = 1; + if (micromips_p) + elfh->other = ELF_ST_SET_MICROMIPS (elfh->other); return TRUE; } @@ -1612,9 +1618,10 @@ mips_elf_create_shadow_symbol (struct bfd_link_info *info, { struct bfd_link_hash_entry *bh; struct elf_link_hash_entry *elfh; - const char *name; + char *name; asection *s; bfd_vma value; + bfd_boolean res; /* Read the symbol's value. */ BFD_ASSERT (h->root.root.type == bfd_link_hash_defined @@ -1623,11 +1630,13 @@ mips_elf_create_shadow_symbol (struct bfd_link_info *info, value = h->root.root.u.def.value; /* Create a new symbol. */ - name = ACONCAT ((prefix, h->root.root.root.string, NULL)); + name = concat (prefix, h->root.root.root.string, NULL); bh = NULL; - if (!_bfd_generic_link_add_one_symbol (info, s->owner, name, - BSF_LOCAL, s, value, NULL, - TRUE, FALSE, &bh)) + res = _bfd_generic_link_add_one_symbol (info, s->owner, name, + BSF_LOCAL, s, value, NULL, + TRUE, FALSE, &bh); + free (name); + if (! res) return FALSE; /* Make it local and copy the other attributes from H. */ @@ -1701,8 +1710,8 @@ mips_elf_check_mips16_stubs (struct bfd_link_info *info, && ! h->need_fn_stub) { /* We don't need the fn_stub; the only references to this symbol - are 16 bit calls. Clobber the size to 0 to prevent it from - being included in the link. */ + are 16 bit calls. Clobber the size to 0 to prevent it from + being included in the link. */ h->fn_stub->size = 0; h->fn_stub->flags &= ~SEC_RELOC; h->fn_stub->reloc_count = 0; @@ -1714,8 +1723,8 @@ mips_elf_check_mips16_stubs (struct bfd_link_info *info, && ELF_ST_IS_MIPS16 (h->root.other)) { /* We don't need the call_stub; this is a 16 bit function, so - calls from other 16 bit functions are OK. Clobber the size - to 0 to prevent it from being included in the link. */ + calls from other 16 bit functions are OK. Clobber the size + to 0 to prevent it from being included in the link. */ h->call_stub->size = 0; h->call_stub->flags &= ~SEC_RELOC; h->call_stub->reloc_count = 0; @@ -1727,8 +1736,8 @@ mips_elf_check_mips16_stubs (struct bfd_link_info *info, && ELF_ST_IS_MIPS16 (h->root.other)) { /* We don't need the call_stub; this is a 16 bit function, so - calls from other 16 bit functions are OK. Clobber the size - to 0 to prevent it from being included in the link. */ + calls from other 16 bit functions are OK. Clobber the size + to 0 to prevent it from being included in the link. */ h->call_fp_stub->size = 0; h->call_fp_stub->flags &= ~SEC_RELOC; h->call_fp_stub->reloc_count = 0; @@ -1799,6 +1808,7 @@ 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) + && !bfd_is_und_section (h->root.root.u.def.section) && (!ELF_ST_IS_MIPS16 (h->root.other) || (h->fn_stub && h->need_fn_stub)) && (PIC_OBJECT_P (h->root.root.u.def.section->owner) @@ -1955,6 +1965,8 @@ mips_elf_add_la25_stub (struct bfd_link_info *info, /* 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); + if (ELF_ST_IS_MICROMIPS (stub->h->root.other)) + value &= ~1; use_trampoline_p = (value != 0 || s->alignment_power > 4); h->la25_stub = stub; @@ -2010,7 +2022,7 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data) +--------------+--------------------------------+ | JALX | X| Imm 20:16 | Imm 25:21 | +--------------+--------------------------------+ - | Immediate 15:0 | + | Immediate 15:0 | +-----------------------------------------------+ JALX is the 5-bit value 00011. X is 0 for jal, 1 for jalx. @@ -2040,16 +2052,16 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data) big-endian: +--------+----------------------+ - | | | - | | targ26-16 | - |31 26|25 0| + | | | + | | targ26-16 | + |31 26|25 0| +--------+----------------------+ little-endian: +----------+------+-------------+ - | | | | - | sub1 | | sub2 | - |0 9|10 15|16 31| + | | | | + | sub1 | | sub2 | + |0 9|10 15|16 31| +----------+--------------------+ where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is ((sub1 << 16) | sub2)). @@ -2084,7 +2096,11 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data) All we need to do here is shuffle the bits appropriately. As above, the two 16-bit halves must be swapped on a - little-endian system. */ + little-endian system. + + Finally R_MIPS16_PC16_S1 corresponds to R_MIPS_PC16, however the + relocatable field is shifted by 1 rather than 2 and the same bit + shuffling is done as with the relocations above. */ static inline bfd_boolean mips16_reloc_p (int r_type) @@ -2104,6 +2120,7 @@ mips16_reloc_p (int r_type) case R_MIPS16_TLS_GOTTPREL: case R_MIPS16_TLS_TPREL_HI16: case R_MIPS16_TLS_TPREL_LO16: + case R_MIPS16_PC16_S1: return TRUE; default: @@ -2209,6 +2226,19 @@ jal_reloc_p (int r_type) || r_type == R_MICROMIPS_26_S1); } +static inline bfd_boolean +b_reloc_p (int r_type) +{ + return (r_type == R_MIPS_PC26_S2 + || r_type == R_MIPS_PC21_S2 + || r_type == R_MIPS_PC16 + || r_type == R_MIPS_GNU_REL16_S2 + || r_type == R_MIPS16_PC16_S1 + || r_type == R_MICROMIPS_PC16_S1 + || r_type == R_MICROMIPS_PC10_S1 + || r_type == R_MICROMIPS_PC7_S1); +} + static inline bfd_boolean aligned_pcrel_reloc_p (int r_type) { @@ -2216,6 +2246,23 @@ aligned_pcrel_reloc_p (int r_type) || r_type == R_MIPS_PC19_S2); } +static inline bfd_boolean +branch_reloc_p (int r_type) +{ + return (r_type == R_MIPS_26 + || r_type == R_MIPS_PC26_S2 + || r_type == R_MIPS_PC21_S2 + || r_type == R_MIPS_PC16 + || r_type == R_MIPS_GNU_REL16_S2); +} + +static inline bfd_boolean +mips16_branch_reloc_p (int r_type) +{ + return (r_type == R_MIPS16_26 + || r_type == R_MIPS16_PC16_S1); +} + static inline bfd_boolean micromips_branch_reloc_p (int r_type) { @@ -2840,7 +2887,7 @@ mips_elf_output_extsym (struct mips_elf_link_hash_entry *h, void *data) const char *name; /* Use undefined class. Also, set class and type for some - special symbols. */ + special symbols. */ name = h->root.root.root.string; if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0 || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0) @@ -3309,7 +3356,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, struct bfd_link_info *info, if (htab == NULL) return; - sgot = htab->sgot; + sgot = htab->root.sgot; indx = 0; if (h != NULL) @@ -3436,8 +3483,8 @@ mips_elf_gotplt_index (struct bfd_link_info *info, BFD_ASSERT (h->plt.plist->gotplt_index != MINUS_ONE); /* Calculate the address of the associated .got.plt entry. */ - got_address = (htab->sgotplt->output_section->vma - + htab->sgotplt->output_offset + got_address = (htab->root.sgotplt->output_section->vma + + htab->root.sgotplt->output_offset + (h->plt.plist->gotplt_index * MIPS_ELF_GOT_SIZE (info->output_bfd))); @@ -3501,7 +3548,7 @@ mips_elf_primary_global_got_index (bfd *obfd, struct bfd_link_info *info, g = mips_elf_bfd_got (obfd, FALSE); got_index = ((h->dynindx - global_got_dynindx + g->local_gotno) * MIPS_ELF_GOT_SIZE (obfd)); - BFD_ASSERT (got_index < htab->sgot->size); + BFD_ASSERT (got_index < htab->root.sgot->size); return got_index; } @@ -3535,7 +3582,7 @@ mips_elf_global_got_index (bfd *obfd, struct bfd_link_info *info, bfd *ibfd, BFD_ASSERT (entry); gotidx = entry->gotidx; - BFD_ASSERT (gotidx > 0 && gotidx < htab->sgot->size); + BFD_ASSERT (gotidx > 0 && gotidx < htab->root.sgot->size); if (lookup.tls_type) { @@ -3623,7 +3670,7 @@ mips_elf_got_offset_from_index (struct bfd_link_info *info, bfd *output_bfd, htab = mips_elf_hash_table (info); BFD_ASSERT (htab != NULL); - sgot = htab->sgot; + sgot = htab->root.sgot; gp = _bfd_get_gp_value (output_bfd) + mips_elf_adjust_gp (output_bfd, htab->got_info, input_bfd); @@ -3686,7 +3733,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info, BFD_ASSERT (entry); gotidx = entry->gotidx; - BFD_ASSERT (gotidx > 0 && gotidx < htab->sgot->size); + BFD_ASSERT (gotidx > 0 && gotidx < htab->root.sgot->size); return entry; } @@ -3705,7 +3752,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info, if (g->assigned_low_gotno > g->assigned_high_gotno) { /* We didn't allocate enough space in the GOT. */ - (*_bfd_error_handler) + _bfd_error_handler (_("not enough GOT space for local GOT entries")); bfd_set_error (bfd_error_bad_value); return NULL; @@ -3726,7 +3773,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info, *entry = lookup; *loc = entry; - MIPS_ELF_PUT_WORD (abfd, value, htab->sgot->contents + entry->gotidx); + MIPS_ELF_PUT_WORD (abfd, value, htab->root.sgot->contents + entry->gotidx); /* These GOT entries need a dynamic relocation on VxWorks. */ if (htab->is_vxworks) @@ -3737,8 +3784,8 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info, bfd_vma got_address; s = mips_elf_rel_dyn_section (info, FALSE); - got_address = (htab->sgot->output_section->vma - + htab->sgot->output_offset + got_address = (htab->root.sgot->output_section->vma + + htab->root.sgot->output_offset + entry->gotidx); rloc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela)); @@ -3788,12 +3835,12 @@ mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info) struct mips_elf_hash_sort_data hsd; struct mips_got_info *g; - if (elf_hash_table (info)->dynsymcount == 0) - return TRUE; - htab = mips_elf_hash_table (info); BFD_ASSERT (htab != NULL); + if (htab->root.dynsymcount == 0) + return TRUE; + g = htab->got_info; if (g == NULL) return TRUE; @@ -3801,20 +3848,19 @@ mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info) hsd.low = NULL; hsd.max_unref_got_dynindx = hsd.min_got_dynindx - = (elf_hash_table (info)->dynsymcount - g->reloc_only_gotno); - hsd.max_non_got_dynindx = count_section_dynsyms (abfd, info) + 1; - mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *) - elf_hash_table (info)), - mips_elf_sort_hash_table_f, - &hsd); + = (htab->root.dynsymcount - g->reloc_only_gotno); + /* Add 1 to local symbol indices to account for the mandatory NULL entry + at the head of the table; see `_bfd_elf_link_renumber_dynsyms'. */ + hsd.max_local_dynindx = count_section_dynsyms (abfd, info) + 1; + hsd.max_non_got_dynindx = htab->root.local_dynsymcount + 1; + mips_elf_link_hash_traverse (htab, mips_elf_sort_hash_table_f, &hsd); /* There should have been enough room in the symbol table to accommodate both the GOT and non-GOT symbols. */ + BFD_ASSERT (hsd.max_local_dynindx <= htab->root.local_dynsymcount + 1); BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx); - BFD_ASSERT ((unsigned long) hsd.max_unref_got_dynindx - == elf_hash_table (info)->dynsymcount); - BFD_ASSERT (elf_hash_table (info)->dynsymcount - hsd.min_got_dynindx - == g->global_gotno); + BFD_ASSERT (hsd.max_unref_got_dynindx == htab->root.dynsymcount); + BFD_ASSERT (htab->root.dynsymcount - hsd.min_got_dynindx == g->global_gotno); /* Now we know which dynamic symbol has the lowest dynamic symbol table index in the GOT. */ @@ -3840,7 +3886,10 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data) switch (h->global_got_area) { case GGA_NONE: - h->root.dynindx = hsd->max_non_got_dynindx++; + if (h->root.forced_local) + h->root.dynindx = hsd->max_local_dynindx++; + else + h->root.dynindx = hsd->max_non_got_dynindx++; break; case GGA_NORMAL: @@ -5090,7 +5139,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) BFD_ASSERT (htab != NULL); /* This function may be called more than once. */ - if (htab->sgot) + if (htab->root.sgot) return TRUE; flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY @@ -5102,7 +5151,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) if (s == NULL || ! bfd_set_section_alignment (abfd, s, 4)) return FALSE; - htab->sgot = s; + htab->root.sgot = s; /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the linker script because we don't want to define the symbol if we @@ -5136,7 +5185,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) | SEC_LINKER_CREATED); if (s == NULL) return FALSE; - htab->sgotplt = s; + htab->root.sgotplt = s; return TRUE; } @@ -5241,6 +5290,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* TRUE if the symbol referred to by this relocation is a local symbol. */ bfd_boolean local_p, was_local_p; + /* TRUE if the symbol referred to by this relocation is a section + symbol. */ + bfd_boolean section_p = FALSE; /* TRUE if the symbol referred to by this relocation is "_gp_disp". */ bfd_boolean gp_disp_p = FALSE; /* TRUE if the symbol referred to by this relocation is @@ -5258,6 +5310,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, bfd_boolean target_is_micromips_code_p = FALSE; struct mips_elf_link_hash_table *htab; bfd *dynobj; + bfd_boolean resolved_to_zero; dynobj = elf_hash_table (info)->dynobj; htab = mips_elf_hash_table (info); @@ -5291,17 +5344,18 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* Figure out the value of the symbol. */ if (local_p) { + bfd_boolean micromips_p = MICROMIPS_P (abfd); Elf_Internal_Sym *sym; sym = local_syms + r_symndx; sec = local_sections[r_symndx]; + section_p = ELF_ST_TYPE (sym->st_info) == STT_SECTION; + symbol = sec->output_section->vma + sec->output_offset; - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION - || (sec->flags & SEC_MERGE)) + if (!section_p || (sec->flags & SEC_MERGE)) symbol += sym->st_value; - if ((sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + if ((sec->flags & SEC_MERGE) && section_p) { addend = _bfd_elf_rel_local_sym (abfd, sym, &sec, addend); addend -= symbol; @@ -5316,11 +5370,29 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, *namep = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); - if (*namep == '\0') + if (*namep == NULL || **namep == '\0') *namep = bfd_section_name (input_bfd, sec); - target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (sym->st_other); - target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (sym->st_other); + /* For relocations against a section symbol and ones against no + symbol (absolute relocations) infer the ISA mode from the addend. */ + if (section_p || r_symndx == STN_UNDEF) + { + target_is_16_bit_code_p = (addend & 1) && !micromips_p; + target_is_micromips_code_p = (addend & 1) && micromips_p; + } + /* For relocations against an absolute symbol infer the ISA mode + from the value of the symbol plus addend. */ + else if (bfd_is_abs_section (sec)) + { + target_is_16_bit_code_p = ((symbol + addend) & 1) && !micromips_p; + target_is_micromips_code_p = ((symbol + addend) & 1) && micromips_p; + } + /* Otherwise just use the regular symbol annotation available. */ + else + { + target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (sym->st_other); + target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (sym->st_other); + } } else { @@ -5385,7 +5457,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, { /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol - in in _bfd_mips_elf_create_dynamic_sections. + in _bfd_mips_elf_create_dynamic_sections. Otherwise, we should define the symbol with a value of 0. FIXME: It should probably get into the symbol table somehow as well. */ @@ -5404,17 +5476,14 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf */ symbol = 0; } - else if ((*info->callbacks->undefined_symbol) - (info, h->root.root.root.string, input_bfd, - input_section, relocation->r_offset, - (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) - || ELF_ST_VISIBILITY (h->root.other))) - { - return bfd_reloc_undefined; - } else { - return bfd_reloc_notsupported; + (*info->callbacks->undefined_symbol) + (info, h->root.root.root.string, input_bfd, + input_section, relocation->r_offset, + (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) + || ELF_ST_VISIBILITY (h->root.other)); + return bfd_reloc_undefined; } target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other); @@ -5507,7 +5576,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, sec = h->call_stub; else sec = h->call_fp_stub; - } + } BFD_ASSERT (sec->size > 0); symbol = sec->output_section->vma + sec->output_offset; @@ -5517,15 +5586,20 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, else if (h != NULL && h->la25_stub && 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); + { + symbol = (h->la25_stub->stub_section->output_section->vma + + h->la25_stub->stub_section->output_offset + + h->la25_stub->offset); + if (ELF_ST_IS_MICROMIPS (h->root.other)) + symbol |= 1; + } /* For direct MIPS16 and microMIPS calls make sure the compressed PLT entry is used if a standard PLT entry has also been made. In this case the symbol will have been set by mips_elf_set_plt_sym_value to point to the standard PLT entry, so redirect to the compressed one. */ - else if ((r_type == R_MIPS16_26 || r_type == R_MICROMIPS_26_S1) + else if ((mips16_branch_reloc_p (r_type) + || micromips_branch_reloc_p (r_type)) && !bfd_link_relocatable (info) && h != NULL && h->use_plt_entry @@ -5534,7 +5608,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, { bfd_boolean micromips_p = MICROMIPS_P (abfd); - sec = htab->splt; + sec = htab->root.splt; symbol = (sec->output_section->vma + sec->output_offset + htab->plt_header_size @@ -5547,10 +5621,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, } /* Make sure MIPS16 and microMIPS are not used together. */ - if ((r_type == R_MIPS16_26 && target_is_micromips_code_p) + if ((mips16_branch_reloc_p (r_type) && target_is_micromips_code_p) || (micromips_branch_reloc_p (r_type) && target_is_16_bit_code_p)) { - (*_bfd_error_handler) + _bfd_error_handler (_("MIPS16 and microMIPS functions cannot call each other")); return bfd_reloc_notsupported; } @@ -5563,10 +5637,12 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, acceptable. */ *cross_mode_jump_p = (!bfd_link_relocatable (info) && !(h && h->root.root.type == bfd_link_hash_undefweak) - && ((r_type == R_MIPS16_26 && !target_is_16_bit_code_p) - || (r_type == R_MICROMIPS_26_S1 + && ((mips16_branch_reloc_p (r_type) + && !target_is_16_bit_code_p) + || (micromips_branch_reloc_p (r_type) && !target_is_micromips_code_p) - || ((r_type == R_MIPS_26 || r_type == R_MIPS_JALR) + || ((branch_reloc_p (r_type) + || r_type == R_MIPS_JALR) && (target_is_16_bit_code_p || target_is_micromips_code_p)))); @@ -5590,6 +5666,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, addend = 0; } + resolved_to_zero = (h != NULL + && UNDEFWEAK_NO_DYNAMIC_RELOC (info, + &h->root)); + /* If we haven't already determined the GOT offset, and we're going to need it, get it now. */ switch (r_type) @@ -5648,7 +5728,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, if (!TLS_RELOC_P (r_type) && !elf_hash_table (info)->dynamic_sections_created) /* This is a static link. We must initialize the GOT entry. */ - MIPS_ELF_PUT_WORD (dynobj, symbol, htab->sgot->contents + g); + MIPS_ELF_PUT_WORD (dynobj, symbol, htab->root.sgot->contents + g); } } else if (!htab->is_vxworks @@ -5721,7 +5801,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, && r_symndx != STN_UNDEF && (h == NULL || h->root.root.type != bfd_link_hash_undefweak - || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) + || (ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT + && !resolved_to_zero)) && (input_section->flags & SEC_ALLOC) != 0) { /* If we're creating a shared library, then we can't know @@ -5767,22 +5848,26 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, { unsigned int shift; - /* Make sure the target of JALX is word-aligned. Bit 0 must be - the correct ISA mode selector and bit 1 must be 0. */ - if (*cross_mode_jump_p && (symbol & 3) != (r_type == R_MIPS_26)) - return bfd_reloc_outofrange; - /* Shift is 2, unusually, for microMIPS JALX. */ shift = (!*cross_mode_jump_p && r_type == R_MICROMIPS_26_S1) ? 1 : 2; - if (was_local_p) - value = addend | ((p + 4) & (0xfc000000 << shift)); - else if (howto->partial_inplace) + if (howto->partial_inplace && !section_p) value = _bfd_mips_elf_sign_extend (addend, 26 + shift); else value = addend; - value = (value + symbol) >> shift; - if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak) + value += symbol; + + /* Make sure the target of a jump is suitably aligned. Bit 0 must + be the correct ISA mode selector except for weak undefined + symbols. */ + if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak) + && (*cross_mode_jump_p + ? (value & 3) != (r_type == R_MIPS_26) + : (value & ((1 << shift) - 1)) != (r_type != R_MIPS_26))) + return bfd_reloc_outofrange; + + value >>= shift; + if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift)); value &= howto->dst_mask; } @@ -5829,9 +5914,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, else { /* For MIPS16 ABI code we generate this sequence - 0: li $v0,%hi(_gp_disp) - 4: addiupc $v1,%lo(_gp_disp) - 8: sll $v0,16 + 0: li $v0,%hi(_gp_disp) + 4: addiupc $v1,%lo(_gp_disp) + 8: sll $v0,16 12: addu $v0,$v1 14: move $gp,$v0 So the offsets of hi and lo relocs are the same, but the @@ -5847,7 +5932,6 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, value = mips_elf_high (addend + gp - p - 1); else value = mips_elf_high (addend + gp - p); - overflowed_p = mips_elf_overflow_p (value, 16); } break; @@ -5969,7 +6053,12 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, if (howto->partial_inplace) addend = _bfd_mips_elf_sign_extend (addend, 18); - if ((symbol + addend) & 3) + /* No need to exclude weak undefined symbols here as they resolve + to 0 and never set `*cross_mode_jump_p', so this alignment check + will never trigger for them. */ + if (*cross_mode_jump_p + ? ((symbol + addend) & 3) != 1 + : ((symbol + addend) & 3) != 0) return bfd_reloc_outofrange; value = symbol + addend - p; @@ -5979,6 +6068,23 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, value &= howto->dst_mask; break; + case R_MIPS16_PC16_S1: + if (howto->partial_inplace) + addend = _bfd_mips_elf_sign_extend (addend, 17); + + if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak) + && (*cross_mode_jump_p + ? ((symbol + addend) & 3) != 0 + : ((symbol + addend) & 1) == 0)) + return bfd_reloc_outofrange; + + value = symbol + addend - p; + if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) + overflowed_p = mips_elf_overflow_p (value, 17); + value >>= howto->rightshift; + value &= howto->dst_mask; + break; + case R_MIPS_PC21_S2: if (howto->partial_inplace) addend = _bfd_mips_elf_sign_extend (addend, 23); @@ -6052,6 +6158,13 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MICROMIPS_PC7_S1: if (howto->partial_inplace) addend = _bfd_mips_elf_sign_extend (addend, 8); + + if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak) + && (*cross_mode_jump_p + ? ((symbol + addend + 2) & 3) != 0 + : ((symbol + addend + 2) & 1) == 0)) + return bfd_reloc_outofrange; + value = symbol + addend - p; if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) overflowed_p = mips_elf_overflow_p (value, 8); @@ -6062,6 +6175,13 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MICROMIPS_PC10_S1: if (howto->partial_inplace) addend = _bfd_mips_elf_sign_extend (addend, 11); + + if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak) + && (*cross_mode_jump_p + ? ((symbol + addend + 2) & 3) != 0 + : ((symbol + addend + 2) & 1) == 0)) + return bfd_reloc_outofrange; + value = symbol + addend - p; if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) overflowed_p = mips_elf_overflow_p (value, 11); @@ -6072,6 +6192,13 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, case R_MICROMIPS_PC16_S1: if (howto->partial_inplace) addend = _bfd_mips_elf_sign_extend (addend, 17); + + if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak) + && (*cross_mode_jump_p + ? ((symbol + addend) & 3) != 0 + : ((symbol + addend) & 1) == 0)) + return bfd_reloc_outofrange; + value = symbol + addend - p; if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) overflowed_p = mips_elf_overflow_p (value, 17); @@ -6157,7 +6284,13 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, when the symbol does not resolve locally. */ if (h != NULL && !SYMBOL_CALLS_LOCAL (info, &h->root)) return bfd_reloc_continue; + /* We can't optimize cross-mode jumps either. */ + if (*cross_mode_jump_p) + return bfd_reloc_continue; value = symbol + addend; + /* Neither we can non-instruction-aligned targets. */ + if (r_type == R_MIPS_JALR ? (value & 3) != 0 : (value & 1) == 0) + return bfd_reloc_continue; break; case R_MIPS_PJUMP: @@ -6230,7 +6363,21 @@ mips_elf_perform_relocation (struct bfd_link_info *info, /* Set the field. */ x |= (value & howto->dst_mask); - /* If required, turn JAL into JALX. */ + /* Detect incorrect JALX usage. If required, turn JAL or BAL into JALX. */ + if (!cross_mode_jump_p && jal_reloc_p (r_type)) + { + bfd_vma opcode = x >> 26; + + if (r_type == R_MIPS16_26 ? opcode == 0x7 + : r_type == R_MICROMIPS_26_S1 ? opcode == 0x3c + : opcode == 0x1d) + { + info->callbacks->einfo + (_("%X%H: Unsupported JALX to the same ISA mode\n"), + input_bfd, input_section, relocation->r_offset); + return TRUE; + } + } if (cross_mode_jump_p && jal_reloc_p (r_type)) { bfd_boolean ok; @@ -6255,21 +6402,72 @@ mips_elf_perform_relocation (struct bfd_link_info *info, } /* If the opcode is not JAL or JALX, there's a problem. We cannot - convert J or JALS to JALX. */ + convert J or JALS to JALX. */ if (!ok) { - (*_bfd_error_handler) - (_("%B: %A+0x%lx: Unsupported jump between ISA modes; consider recompiling with interlinking enabled."), - input_bfd, - input_section, - (unsigned long) relocation->r_offset); - bfd_set_error (bfd_error_bad_value); - return FALSE; + info->callbacks->einfo + (_("%X%H: Unsupported jump between ISA modes; " + "consider recompiling with interlinking enabled\n"), + input_bfd, input_section, relocation->r_offset); + return TRUE; } /* Make this the JALX opcode. */ x = (x & ~(0x3f << 26)) | (jalx_opcode << 26); } + else if (cross_mode_jump_p && b_reloc_p (r_type)) + { + bfd_boolean ok = FALSE; + bfd_vma opcode = x >> 16; + bfd_vma jalx_opcode = 0; + bfd_vma sign_bit = 0; + bfd_vma addr; + bfd_vma dest; + + if (r_type == R_MICROMIPS_PC16_S1) + { + ok = opcode == 0x4060; + jalx_opcode = 0x3c; + sign_bit = 0x10000; + value <<= 1; + } + else if (r_type == R_MIPS_PC16 || r_type == R_MIPS_GNU_REL16_S2) + { + ok = opcode == 0x411; + jalx_opcode = 0x1d; + sign_bit = 0x20000; + value <<= 2; + } + + if (ok && !bfd_link_pic (info)) + { + addr = (input_section->output_section->vma + + input_section->output_offset + + relocation->r_offset + + 4); + dest = (addr + + (((value & ((sign_bit << 1) - 1)) ^ sign_bit) - sign_bit)); + + if ((addr >> 28) << 28 != (dest >> 28) << 28) + { + info->callbacks->einfo + (_("%X%H: Cannot convert branch between ISA modes " + "to JALX: relocation out of range\n"), + input_bfd, input_section, relocation->r_offset); + return TRUE; + } + + /* Make this the JALX opcode. */ + x = ((dest >> 2) & 0x3ffffff) | jalx_opcode << 26; + } + else if (!mips_elf_hash_table (info)->ignore_branch_isa) + { + info->callbacks->einfo + (_("%X%H: Unsupported branch between ISA modes\n"), + input_bfd, input_section, relocation->r_offset); + return TRUE; + } + } /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in range. */ @@ -6277,13 +6475,13 @@ mips_elf_perform_relocation (struct bfd_link_info *info, && !cross_mode_jump_p && ((JAL_TO_BAL_P (input_bfd) && r_type == R_MIPS_26 - && (x >> 26) == 0x3) /* jal addr */ + && (x >> 26) == 0x3) /* jal addr */ || (JALR_TO_BAL_P (input_bfd) && r_type == R_MIPS_JALR - && x == 0x0320f809) /* jalr t9 */ + && x == 0x0320f809) /* jalr t9 */ || (JR_TO_B_P (input_bfd) && r_type == R_MIPS_JALR - && x == 0x03200008))) /* jr t9 */ + && (x & ~1) == 0x03200008))) /* jr t9 / jalr zero, t9 */ { bfd_vma addr; bfd_vma dest; @@ -6300,7 +6498,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info, off = dest - addr; if (off <= 0x1ffff && off >= -0x20000) { - if (x == 0x03200008) /* jr t9 */ + if ((x & ~1) == 0x03200008) /* jr t9 / jalr zero, t9 */ x = 0x10000000 | (((bfd_vma) off >> 2) & 0xffff); /* b addr */ else x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff); /* bal addr */ @@ -6605,6 +6803,9 @@ _bfd_elf_mips_mach (flagword flags) case E_MIPS_MACH_XLR: return bfd_mach_mips_xlr; + case E_MIPS_MACH_IAMR2: + return bfd_mach_mips_interaptiv_mr2; + default: switch (flags & EF_MIPS_ARCH) { @@ -6764,7 +6965,7 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym) { asym->section = section; /* MIPS_TEXT is a bit special, the address is not an offset - to the base of the .text section. So substract the section + to the base of the .text section. So subtract the section base address to make it an offset. */ asym->value -= section->vma; } @@ -6779,7 +6980,7 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym) { asym->section = section; /* MIPS_DATA is a bit special, the address is not an offset - to the base of the .data section. So substract the section + to the base of the .data section. So subtract the section base address to make it an offset. */ asym->value -= section->vma; } @@ -6822,10 +7023,10 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym) We therefore take the following approach: - If ABFD contains a .gcc_compiled_longXX section, use it to - determine the pointer size. + determine the pointer size. - Otherwise check the type of the first relocation. Assume that - the LP64 ABI is being used if the relocation is of type R_MIPS_64. + the LP64 ABI is being used if the relocation is of type R_MIPS_64. - Otherwise punt. @@ -6840,7 +7041,7 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym) did so. */ unsigned int -_bfd_mips_elf_eh_frame_address_size (bfd *abfd, asection *sec) +_bfd_mips_elf_eh_frame_address_size (bfd *abfd, const asection *sec) { if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) return 8; @@ -6901,9 +7102,19 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr) { bfd_byte buf[4]; - BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo)); BFD_ASSERT (hdr->contents == NULL); + if (hdr->sh_size != sizeof (Elf32_External_RegInfo)) + { + _bfd_error_handler + (_("%pB: Incorrect `.reginfo' section size; " + "expected %" PRIu64 ", got %" PRIu64), + abfd, (uint64_t) sizeof (Elf32_External_RegInfo), + (uint64_t) hdr->sh_size); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + if (bfd_seek (abfd, hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4, SEEK_SET) != 0) @@ -6938,8 +7149,10 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr) &intopt); if (intopt.size < sizeof (Elf_External_Options)) { - (*_bfd_error_handler) - (_("%B: Warning: bad `%s' option size %u smaller than its header"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Warning: bad `%s' option size %u smaller than" + " its header"), abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size); break; } @@ -7084,7 +7297,7 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd, break; case SHT_MIPS_DWARF: if (! CONST_STRNEQ (name, ".debug_") - && ! CONST_STRNEQ (name, ".zdebug_")) + && ! CONST_STRNEQ (name, ".zdebug_")) return FALSE; break; case SHT_MIPS_SYMBOL_LIB: @@ -7171,8 +7384,10 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd, &intopt); if (intopt.size < sizeof (Elf_External_Options)) { - (*_bfd_error_handler) - (_("%B: Warning: bad `%s' option size %u smaller than its header"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Warning: bad `%s' option size %u smaller than" + " its header"), abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size); break; } @@ -7235,7 +7450,7 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) { hdr->sh_type = SHT_MIPS_DEBUG; /* In a shared object on IRIX 5.3, the .mdebug section has an - entsize of 0. FIXME: Does this matter? */ + entsize of 0. FIXME: Does this matter? */ if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0) hdr->sh_entsize = 0; else @@ -7245,7 +7460,7 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) { hdr->sh_type = SHT_MIPS_REGINFO; /* In a shared object on IRIX 5.3, the .reginfo section has an - entsize of 0x18. FIXME: Does this matter? */ + entsize of 0x18. FIXME: Does this matter? */ if (SGI_COMPAT (abfd)) { if ((abfd->flags & DYNAMIC) != 0) @@ -7298,7 +7513,7 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) hdr->sh_entsize = sizeof (Elf_External_ABIFlags_v0); } else if (CONST_STRNEQ (name, ".debug_") - || CONST_STRNEQ (name, ".zdebug_")) + || CONST_STRNEQ (name, ".zdebug_")) { hdr->sh_type = SHT_MIPS_DWARF; @@ -7312,7 +7527,7 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) { hdr->sh_type = SHT_MIPS_SYMBOL_LIB; /* The sh_link and sh_info fields are set in - final_write_processing. */ + final_write_processing. */ } else if (CONST_STRNEQ (name, ".MIPS.events") || CONST_STRNEQ (name, ".MIPS.post_rel")) @@ -7442,8 +7657,8 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, elf_text_symbol->section = elf_text_section; } /* This code used to do *secp = bfd_und_section_ptr if - bfd_link_pic (info). I don't know why, and that doesn't make sense, - so I took it out. */ + bfd_link_pic (info). I don't know why, and that doesn't make sense, + so I took it out. */ *secp = mips_elf_tdata (abfd)->elf_text_section; break; @@ -7483,8 +7698,8 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, elf_data_symbol->section = elf_data_section; } /* This code used to do *secp = bfd_und_section_ptr if - bfd_link_pic (info). I don't know why, and that doesn't make sense, - so I took it out. */ + bfd_link_pic (info). I don't know why, and that doesn't make sense, + so I took it out. */ *secp = mips_elf_tdata (abfd)->elf_data_section; break; @@ -7717,22 +7932,6 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (!_bfd_elf_create_dynamic_sections (abfd, info)) return FALSE; - /* Cache the sections created above. */ - htab->splt = bfd_get_linker_section (abfd, ".plt"); - htab->sdynbss = bfd_get_linker_section (abfd, ".dynbss"); - if (htab->is_vxworks) - { - htab->srelbss = bfd_get_linker_section (abfd, ".rela.bss"); - htab->srelplt = bfd_get_linker_section (abfd, ".rela.plt"); - } - else - htab->srelplt = bfd_get_linker_section (abfd, ".rel.plt"); - if (!htab->sdynbss - || (htab->is_vxworks && !htab->srelbss && !bfd_link_pic (info)) - || !htab->srelplt - || !htab->splt) - abort (); - /* Do the usual VxWorks handling. */ if (htab->is_vxworks && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2)) @@ -7774,16 +7973,24 @@ mips_elf_read_rel_addend (bfd *abfd, const Elf_Internal_Rela *rel, bfd_byte *location; unsigned int r_type; bfd_vma addend; + bfd_vma bytes; r_type = ELF_R_TYPE (abfd, rel->r_info); location = contents + rel->r_offset; /* Get the addend, which is stored in the input file. */ _bfd_mips_elf_reloc_unshuffle (abfd, r_type, FALSE, location); - addend = mips_elf_obtain_contents (howto, rel, abfd, contents); + bytes = mips_elf_obtain_contents (howto, rel, abfd, contents); _bfd_mips_elf_reloc_shuffle (abfd, r_type, FALSE, location); - return addend & howto->src_mask; + addend = bytes & howto->src_mask; + + /* Shift is 2, unusually, for microMIPS JALX. Adjust the addend + accordingly. */ + if (r_type == R_MICROMIPS_26_S1 && (bytes >> 26) == 0x3c) + addend <<= 1; + + return addend; } /* REL is a relocation in ABFD that needs a partnering LO16 relocation @@ -7918,7 +8125,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info; bed = get_elf_backend_data (abfd); - rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel; + rel_end = relocs + sec->reloc_count; /* Check for the mips16 stub sections. */ @@ -7928,13 +8135,14 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, unsigned long r_symndx; /* Look at the relocation information to figure out which symbol - this is for. */ + this is for. */ r_symndx = mips16_stub_symndx (bed, sec, relocs, rel_end); if (r_symndx == 0) { - (*_bfd_error_handler) - (_("%B: Warning: cannot determine the target function for" + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Warning: cannot determine the target function for" " stub section `%s'"), abfd, name); bfd_set_error (bfd_error_bad_value); @@ -7947,8 +8155,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *o; /* This stub is for a local symbol. This stub will only be - needed if there is some relocation in this BFD, other - than a 16 bit function call, which refers to this symbol. */ + needed if there is some relocation in this BFD, other + than a 16 bit function call, which refers to this symbol. */ for (o = abfd->sections; o != NULL; o = o->next) { Elf_Internal_Rela *sec_relocs; @@ -7982,16 +8190,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (o == NULL) { /* There is no non-call reloc for this stub, so we do - not need it. Since this function is called before - the linker maps input sections to output sections, we - can easily discard it by setting the SEC_EXCLUDE - flag. */ + not need it. Since this function is called before + the linker maps input sections to output sections, we + can easily discard it by setting the SEC_EXCLUDE + flag. */ sec->flags |= SEC_EXCLUDE; return TRUE; } /* Record this stub in an array of local symbol stubs for - this BFD. */ + this BFD. */ if (mips_elf_tdata (abfd)->local_stubs == NULL) { unsigned long symcount; @@ -8013,9 +8221,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, mips_elf_tdata (abfd)->local_stubs[r_symndx] = sec; /* We don't need to set mips16_stubs_seen in this case. - That flag is used to see whether we need to look through - the global symbol table for stubs. We don't need to set - it here, because we just have a local stub. */ + That flag is used to see whether we need to look through + the global symbol table for stubs. We don't need to set + it here, because we just have a local stub. */ } else { @@ -8053,13 +8261,14 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection **loc; /* Look at the relocation information to figure out which symbol - this is for. */ + this is for. */ r_symndx = mips16_stub_symndx (bed, sec, relocs, rel_end); if (r_symndx == 0) { - (*_bfd_error_handler) - (_("%B: Warning: cannot determine the target function for" + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Warning: cannot determine the target function for" " stub section `%s'"), abfd, name); bfd_set_error (bfd_error_bad_value); @@ -8072,8 +8281,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *o; /* This stub is for a local symbol. This stub will only be - needed if there is some relocation (R_MIPS16_26) in this BFD - that refers to this symbol. */ + needed if there is some relocation (R_MIPS16_26) in this BFD + that refers to this symbol. */ for (o = abfd->sections; o != NULL; o = o->next) { Elf_Internal_Rela *sec_relocs; @@ -8107,16 +8316,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (o == NULL) { /* There is no non-call reloc for this stub, so we do - not need it. Since this function is called before - the linker maps input sections to output sections, we - can easily discard it by setting the SEC_EXCLUDE - flag. */ + not need it. Since this function is called before + the linker maps input sections to output sections, we + can easily discard it by setting the SEC_EXCLUDE + flag. */ sec->flags |= SEC_EXCLUDE; return TRUE; } /* Record this stub in an array of local symbol call_stubs for - this BFD. */ + this BFD. */ if (mips_elf_tdata (abfd)->local_call_stubs == NULL) { unsigned long symcount; @@ -8138,9 +8347,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, mips_elf_tdata (abfd)->local_call_stubs[r_symndx] = sec; /* We don't need to set mips16_stubs_seen in this case. - That flag is used to see whether we need to look through - the global symbol table for stubs. We don't need to set - it here, because we just have a local stub. */ + That flag is used to see whether we need to look through + the global symbol table for stubs. We don't need to set + it here, because we just have a local stub. */ } else { @@ -8189,8 +8398,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h = NULL; else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr)) { - (*_bfd_error_handler) - (_("%B: Malformed reloc detected for section %s"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Malformed reloc detected for section %s"), abfd, name); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -8203,10 +8413,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *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; - - /* PR15323, ref flags aren't set for references in the - same object. */ - h->root.non_ir_ref = 1; } } @@ -8264,9 +8470,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, return FALSE; if (htab->is_vxworks && !bfd_link_pic (info)) { - (*_bfd_error_handler) - (_("%B: GOT reloc at 0x%lx not expected in executables"), - abfd, (unsigned long) rel->r_offset); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: GOT reloc at %#" PRIx64 " not expected in executables"), + abfd, (uint64_t) rel->r_offset); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -8325,6 +8532,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_MIPS_PC21_S2: case R_MIPS_PC26_S2: case R_MIPS16_26: + case R_MIPS16_PC16_S1: case R_MICROMIPS_26_S1: case R_MICROMIPS_PC7_S1: case R_MICROMIPS_PC10_S1: @@ -8400,9 +8608,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_MICROMIPS_CALL16: if (h == NULL) { - (*_bfd_error_handler) - (_("%B: CALL16 reloc at 0x%lx not against global symbol"), - abfd, (unsigned long) rel->r_offset); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: CALL16 reloc at %#" PRIx64 " not against global symbol"), + abfd, (uint64_t) rel->r_offset); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -8611,14 +8820,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } /* Record the need for a PLT entry. At this point we don't know - yet if we are going to create a PLT in the first place, but - we only record whether the relocation requires a standard MIPS - or a compressed code entry anyway. If we don't make a PLT after - all, then we'll just ignore these arrangements. Likewise if - a PLT entry is not created because the symbol is satisfied - locally. */ + yet if we are going to create a PLT in the first place, but + we only record whether the relocation requires a standard MIPS + or a compressed code entry anyway. If we don't make a PLT after + all, then we'll just ignore these arrangements. Likewise if + a PLT entry is not created because the symbol is satisfied + locally. */ if (h != NULL - && jal_reloc_p (r_type) + && (branch_reloc_p (r_type) + || mips16_branch_reloc_p (r_type) + || micromips_branch_reloc_p (r_type)) && !SYMBOL_CALLS_LOCAL (info, h)) { if (h->plt.plist == NULL) @@ -8626,7 +8837,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (h->plt.plist == NULL) return FALSE; - if (r_type == R_MIPS_26) + if (branch_reloc_p (r_type)) h->plt.plist->need_mips = TRUE; else h->plt.plist->need_comp = TRUE; @@ -8683,8 +8894,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_MIPS_26: case R_MICROMIPS_26_S1: howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, FALSE); - (*_bfd_error_handler) - (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: relocation %s against `%s' can not be used" + " when making a shared object; recompile with -fPIC"), abfd, howto->name, (h) ? h->root.root.string : "a local symbol"); bfd_set_error (bfd_error_bad_value); @@ -8698,167 +8911,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, return TRUE; } -bfd_boolean -_bfd_mips_relax_section (bfd *abfd, asection *sec, - struct bfd_link_info *link_info, - bfd_boolean *again) -{ - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *irel, *irelend; - Elf_Internal_Shdr *symtab_hdr; - bfd_byte *contents = NULL; - size_t extsymoff; - bfd_boolean changed_contents = FALSE; - bfd_vma sec_start = sec->output_section->vma + sec->output_offset; - Elf_Internal_Sym *isymbuf = NULL; - - /* We are not currently changing any sizes, so only one pass. */ - *again = FALSE; - - if (bfd_link_relocatable (link_info)) - return TRUE; - - internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, - link_info->keep_memory); - if (internal_relocs == NULL) - return TRUE; - - irelend = internal_relocs + sec->reloc_count - * get_elf_backend_data (abfd)->s->int_rels_per_ext_rel; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info; - - for (irel = internal_relocs; irel < irelend; irel++) - { - bfd_vma symval; - bfd_signed_vma sym_offset; - unsigned int r_type; - unsigned long r_symndx; - asection *sym_sec; - unsigned long instruction; - - /* Turn jalr into bgezal, and jr into beq, if they're marked - with a JALR relocation, that indicate where they jump to. - This saves some pipeline bubbles. */ - r_type = ELF_R_TYPE (abfd, irel->r_info); - if (r_type != R_MIPS_JALR) - continue; - - r_symndx = ELF_R_SYM (abfd, irel->r_info); - /* Compute the address of the jump target. */ - if (r_symndx >= extsymoff) - { - struct mips_elf_link_hash_entry *h - = ((struct mips_elf_link_hash_entry *) - elf_sym_hashes (abfd) [r_symndx - extsymoff]); - - while (h->root.root.type == bfd_link_hash_indirect - || h->root.root.type == bfd_link_hash_warning) - h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link; - - /* If a symbol is undefined, or if it may be overridden, - skip it. */ - if (! ((h->root.root.type == bfd_link_hash_defined - || h->root.root.type == bfd_link_hash_defweak) - && h->root.root.u.def.section) - || (bfd_link_pic (link_info) && ! link_info->symbolic - && !h->root.forced_local)) - continue; - - sym_sec = h->root.root.u.def.section; - if (sym_sec->output_section) - symval = (h->root.root.u.def.value - + sym_sec->output_section->vma - + sym_sec->output_offset); - else - symval = h->root.root.u.def.value; - } - else - { - Elf_Internal_Sym *isym; - - /* Read this BFD's symbols if we haven't done so already. */ - if (isymbuf == NULL && symtab_hdr->sh_info != 0) - { - isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; - if (isymbuf == NULL) - isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, - symtab_hdr->sh_info, 0, - NULL, NULL, NULL); - if (isymbuf == NULL) - goto relax_return; - } - - isym = isymbuf + r_symndx; - if (isym->st_shndx == SHN_UNDEF) - continue; - else if (isym->st_shndx == SHN_ABS) - sym_sec = bfd_abs_section_ptr; - else if (isym->st_shndx == SHN_COMMON) - sym_sec = bfd_com_section_ptr; - else - sym_sec - = bfd_section_from_elf_index (abfd, isym->st_shndx); - symval = isym->st_value - + sym_sec->output_section->vma - + sym_sec->output_offset; - } - - /* Compute branch offset, from delay slot of the jump to the - branch target. */ - sym_offset = (symval + irel->r_addend) - - (sec_start + irel->r_offset + 4); - - /* Branch offset must be properly aligned. */ - if ((sym_offset & 3) != 0) - continue; - - sym_offset >>= 2; - - /* Check that it's in range. */ - if (sym_offset < -0x8000 || sym_offset >= 0x8000) - continue; - - /* Get the section contents if we haven't done so already. */ - if (!mips_elf_get_section_contents (abfd, sec, &contents)) - goto relax_return; - - instruction = bfd_get_32 (abfd, contents + irel->r_offset); - - /* If it was jalr , turn it into bgezal $zero, . */ - if ((instruction & 0xfc1fffff) == 0x0000f809) - instruction = 0x04110000; - /* If it was jr , turn it into b . */ - else if ((instruction & 0xfc1fffff) == 0x00000008) - instruction = 0x10000000; - else - continue; - - instruction |= (sym_offset & 0xffff); - bfd_put_32 (abfd, instruction, contents + irel->r_offset); - changed_contents = TRUE; - } - - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - { - if (!changed_contents && !link_info->keep_memory) - free (contents); - else - { - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; - } - } - return TRUE; - - relax_return: - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - free (contents); - return FALSE; -} - /* Allocate space for global sym dynamic relocs. */ static bfd_boolean @@ -8900,7 +8952,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { /* Do not copy relocations for undefined weak symbols with non-default visibility. */ - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) do_copy = FALSE; /* Make sure undefined weak symbols are output as a dynamic @@ -8954,6 +9007,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, bfd *dynobj; struct mips_elf_link_hash_entry *hmips; struct mips_elf_link_hash_table *htab; + asection *s, *srel; htab = mips_elf_hash_table (info); BFD_ASSERT (htab != NULL); @@ -8964,7 +9018,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL && (h->needs_plt - || h->u.weakdef != NULL + || h->is_weakalias || (h->def_dynamic && h->ref_regular && !h->def_regular))); @@ -9016,11 +9070,11 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, bfd_boolean newabi_p = NEWABI_P (info->output_bfd); /* If this is the first symbol to need a PLT entry, then make some - basic setup. Also work out PLT entry sizes. We'll need them - for PLT offset calculations. */ + basic setup. Also work out PLT entry sizes. We'll need them + for PLT offset calculations. */ if (htab->plt_mips_offset + htab->plt_comp_offset == 0) { - BFD_ASSERT (htab->sgotplt->size == 0); + BFD_ASSERT (htab->root.sgotplt->size == 0); BFD_ASSERT (htab->plt_got_index == 0); /* If we're using the PLT additions to the psABI, each PLT @@ -9028,12 +9082,12 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, Encourage better cache usage by aligning. We do this lazily to avoid pessimizing traditional objects. */ if (!htab->is_vxworks - && !bfd_set_section_alignment (dynobj, htab->splt, 5)) + && !bfd_set_section_alignment (dynobj, htab->root.splt, 5)) return FALSE; /* Make sure that .got.plt is word-aligned. We do this lazily for the same reason as above. */ - if (!bfd_set_section_alignment (dynobj, htab->sgotplt, + if (!bfd_set_section_alignment (dynobj, htab->root.sgotplt, MIPS_ELF_LOG_FILE_ALIGN (dynobj))) return FALSE; @@ -9088,13 +9142,13 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, return FALSE; /* There are no defined MIPS16 or microMIPS PLT entries for VxWorks, - n32 or n64, so always use a standard entry there. + n32 or n64, so always use a standard entry there. - If the symbol has a MIPS16 call stub and gets a PLT entry, then - all MIPS16 calls will go via that stub, and there is no benefit - to having a MIPS16 entry. And in the case of call_stub a - standard entry actually has to be used as the stub ends with a J - instruction. */ + If the symbol has a MIPS16 call stub and gets a PLT entry, then + all MIPS16 calls will go via that stub, and there is no benefit + to having a MIPS16 entry. And in the case of call_stub a + standard entry actually has to be used as the stub ends with a J + instruction. */ if (newabi_p || htab->is_vxworks || hmips->call_stub @@ -9105,11 +9159,11 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, } /* Otherwise, if there are no direct calls to the function, we - have a free choice of whether to use standard or compressed - entries. Prefer microMIPS entries if the object is known to - contain microMIPS code, so that it becomes possible to create - pure microMIPS binaries. Prefer standard entries otherwise, - because MIPS16 ones are no smaller and are usually slower. */ + have a free choice of whether to use standard or compressed + entries. Prefer microMIPS entries if the object is known to + contain microMIPS code, so that it becomes possible to create + pure microMIPS binaries. Prefer standard entries otherwise, + because MIPS16 ones are no smaller and are usually slower. */ if (!h->plt.plist->need_mips && !h->plt.plist->need_comp) { if (micromips_p) @@ -9138,9 +9192,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, hmips->use_plt_entry = TRUE; /* Make room for the R_MIPS_JUMP_SLOT relocation. */ - htab->srelplt->size += (htab->is_vxworks - ? MIPS_ELF_RELA_SIZE (dynobj) - : MIPS_ELF_REL_SIZE (dynobj)); + htab->root.srelplt->size += (htab->is_vxworks + ? MIPS_ELF_RELA_SIZE (dynobj) + : MIPS_ELF_REL_SIZE (dynobj)); /* Make room for the .rela.plt.unloaded relocations. */ if (htab->is_vxworks && !bfd_link_pic (info)) @@ -9156,12 +9210,12 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the 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 - || h->u.weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->u.weakdef->root.u.def.section; - h->root.u.def.value = h->u.weakdef->root.u.def.value; + struct elf_link_hash_entry *def = weakdef (h); + BFD_ASSERT (def->root.type == bfd_link_hash_defined); + h->root.u.def.section = def->root.u.def.section; + h->root.u.def.value = def->root.u.def.value; return TRUE; } @@ -9179,9 +9233,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, some that we can't convert. */ if (!htab->use_plts_and_copy_relocs || bfd_link_pic (info)) { - (*_bfd_error_handler) (_("non-dynamic relocations refer to " - "dynamic symbol %s"), - h->root.root.string); + _bfd_error_handler (_("non-dynamic relocations refer to " + "dynamic symbol %s"), + h->root.root.string); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -9196,10 +9250,20 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, both the dynamic object and the regular object will refer to the same memory location for the variable. */ + 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 (htab->is_vxworks) - htab->srelbss->size += sizeof (Elf32_External_Rela); + srel->size += sizeof (Elf32_External_Rela); else mips_elf_allocate_dynamic_relocations (dynobj, info, 1); h->needs_copy = 1; @@ -9209,7 +9273,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, dynamic will now refer to the local copy instead. */ hmips->possibly_dynamic_relocs = 0; - return _bfd_elf_adjust_dynamic_copy (info, h, htab->sdynbss); + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* This function is called after all the input files have been read, @@ -9265,7 +9329,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info) htab = mips_elf_hash_table (info); BFD_ASSERT (htab != NULL); - s = htab->sgot; + s = htab->root.sgot; if (s == NULL) return TRUE; @@ -9538,12 +9602,12 @@ mips_elf_set_plt_sym_value (struct mips_elf_link_hash_entry *h, void *data) } val += isa_bit; /* For VxWorks, point at the PLT load stub rather than the lazy - resolution stub; this stub will become the canonical function - address. */ + resolution stub; this stub will become the canonical function + address. */ if (htab->is_vxworks) val += 8; - h->root.root.u.def.section = htab->splt; + h->root.root.u.def.section = htab->root.splt; h->root.root.u.def.value = val; h->root.other = other; } @@ -9581,18 +9645,18 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, } /* Figure out the size of the PLT header if we know that we - are using it. For the sake of cache alignment always use - a standard header whenever any standard entries are present - even if microMIPS entries are present as well. This also - lets the microMIPS header rely on the value of $v0 only set - by microMIPS entries, for a small size reduction. + are using it. For the sake of cache alignment always use + a standard header whenever any standard entries are present + even if microMIPS entries are present as well. This also + lets the microMIPS header rely on the value of $v0 only set + by microMIPS entries, for a small size reduction. - Set symbol table entry values for symbols that use the - address of their PLT entry now that we can calculate it. + Set symbol table entry values for symbols that use the + address of their PLT entry now that we can calculate it. - Also create the _PROCEDURE_LINKAGE_TABLE_ symbol if we - haven't already in _bfd_elf_create_dynamic_sections. */ - if (htab->splt && htab->plt_mips_offset + htab->plt_comp_offset != 0) + Also create the _PROCEDURE_LINKAGE_TABLE_ symbol if we + haven't already in _bfd_elf_create_dynamic_sections. */ + if (htab->root.splt && htab->plt_mips_offset + htab->plt_comp_offset != 0) { bfd_boolean micromips_p = (MICROMIPS_P (output_bfd) && !htab->plt_mips_offset); @@ -9602,8 +9666,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, bfd_vma size; BFD_ASSERT (htab->use_plts_and_copy_relocs); - BFD_ASSERT (htab->sgotplt->size == 0); - BFD_ASSERT (htab->splt->size == 0); + BFD_ASSERT (htab->root.sgotplt->size == 0); + BFD_ASSERT (htab->root.splt->size == 0); if (htab->is_vxworks && bfd_link_pic (info)) size = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry); @@ -9622,17 +9686,17 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, htab->plt_header_is_comp = micromips_p; htab->plt_header_size = size; - htab->splt->size = (size - + htab->plt_mips_offset - + htab->plt_comp_offset); - htab->sgotplt->size = (htab->plt_got_index - * MIPS_ELF_GOT_SIZE (dynobj)); + htab->root.splt->size = (size + + htab->plt_mips_offset + + htab->plt_comp_offset); + htab->root.sgotplt->size = (htab->plt_got_index + * MIPS_ELF_GOT_SIZE (dynobj)); mips_elf_link_hash_traverse (htab, mips_elf_set_plt_sym_value, info); if (htab->root.hplt == NULL) { - h = _bfd_elf_define_linkage_sym (dynobj, info, htab->splt, + h = _bfd_elf_define_linkage_sym (dynobj, info, htab->root.splt, "_PROCEDURE_LINKAGE_TABLE_"); htab->root.hplt = h; if (h == NULL) @@ -9679,11 +9743,11 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, asection *target; /* If this relocation section applies to a read only - section, then we probably need a DT_TEXTREL entry. - If the relocation section is .rel(a).dyn, we always - assert a DT_TEXTREL entry rather than testing whether - there exists a relocation to a read only section or - not. */ + section, then we probably need a DT_TEXTREL entry. + If the relocation section is .rel(a).dyn, we always + assert a DT_TEXTREL entry rather than testing whether + there exists a relocation to a read only section or + not. */ outname = bfd_get_section_name (output_bfd, s->output_section); target = bfd_get_section_by_name (output_bfd, outname + 4); @@ -9718,7 +9782,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, else if (SGI_COMPAT (output_bfd) && CONST_STRNEQ (name, ".compact_rel")) s->size += mips_elf_hash_table (info)->compact_rel_size; - else if (s == htab->splt) + else if (s == htab->root.splt) { /* If the last PLT entry has a branch delay slot, allocate room for an extra nop to fill the delay slot. This is @@ -9728,10 +9792,11 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, s->size += 4; } else if (! CONST_STRNEQ (name, ".init") - && s != htab->sgot - && s != htab->sgotplt + && s != htab->root.sgot + && s != htab->root.sgotplt && s != htab->sstubs - && s != htab->sdynbss) + && s != htab->root.sdynbss + && s != htab->root.sdynrelro) { /* It's not one of our sections, so don't allocate space. */ continue; @@ -9861,7 +9926,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0)) return FALSE; } - if (htab->splt->size > 0) + if (htab->root.splt->size > 0) { if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0)) return FALSE; @@ -9986,10 +10051,8 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, const Elf_Internal_Rela *relend; bfd_vma addend = 0; bfd_boolean use_saved_addend_p = FALSE; - const struct elf_backend_data *bed; - bed = get_elf_backend_data (output_bfd); - relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel; + relend = relocs + input_section->reloc_count; for (rel = relocs; rel < relend; ++rel) { const char *name; @@ -9997,7 +10060,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, reloc_howto_type *howto; bfd_boolean cross_mode_jump_p = FALSE; /* TRUE if the relocation is a RELA relocation, rather than a - REL relocation. */ + REL relocation. */ bfd_boolean rela_relocation_p = TRUE; unsigned int r_type = ELF_R_TYPE (output_bfd, rel->r_info); const char *msg; @@ -10088,10 +10151,12 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, name = bfd_elf_sym_name (input_bfd, symtab_hdr, local_syms + r_symndx, sec); - (*_bfd_error_handler) - (_("%B: Can't find matching LO16 reloc against `%s' for %s at 0x%lx in section `%A'"), - input_bfd, input_section, name, howto->name, - rel->r_offset); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Can't find matching LO16 reloc against `%s'" + " for %s at %#" PRIx64 " in section `%pA'"), + input_bfd, name, + howto->name, (uint64_t) rel->r_offset, input_section); } } else @@ -10234,10 +10299,9 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, htab->small_data_overflow_reported = TRUE; (*info->callbacks->einfo) ("%P: %s\n", msg); } - if (! ((*info->callbacks->reloc_overflow) - (info, NULL, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset))) - return FALSE; + (*info->callbacks->reloc_overflow) + (info, NULL, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset); } break; @@ -10245,19 +10309,26 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, break; case bfd_reloc_outofrange: + msg = NULL; if (jal_reloc_p (howto->type)) + msg = (cross_mode_jump_p + ? _("Cannot convert a jump to JALX " + "for a non-word-aligned address") + : (howto->type == R_MIPS16_26 + ? _("Jump to a non-word-aligned address") + : _("Jump to a non-instruction-aligned address"))); + else if (b_reloc_p (howto->type)) + msg = (cross_mode_jump_p + ? _("Cannot convert a branch to JALX " + "for a non-word-aligned address") + : _("Branch to a non-instruction-aligned address")); + else if (aligned_pcrel_reloc_p (howto->type)) + msg = _("PC-relative load from unaligned address"); + if (msg) { - msg = _("JALX to a non-word-aligned address"); - info->callbacks->warning - (info, msg, name, input_bfd, input_section, rel->r_offset); - return FALSE; - } - if (aligned_pcrel_reloc_p (howto->type)) - { - msg = _("PC-relative load from unaligned address"); - info->callbacks->warning - (info, msg, name, input_bfd, input_section, rel->r_offset); - return FALSE; + info->callbacks->einfo + ("%X%H: %s\n", input_bfd, input_section, rel->r_offset, msg); + break; } /* Fall through. */ @@ -10506,32 +10577,32 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT (htab->use_plts_and_copy_relocs); BFD_ASSERT (h->dynindx != -1); - BFD_ASSERT (htab->splt != NULL); + BFD_ASSERT (htab->root.splt != NULL); BFD_ASSERT (got_index != MINUS_ONE); BFD_ASSERT (!h->def_regular); /* Calculate the address of the PLT header. */ isa_bit = htab->plt_header_is_comp; - header_address = (htab->splt->output_section->vma - + htab->splt->output_offset + isa_bit); + header_address = (htab->root.splt->output_section->vma + + htab->root.splt->output_offset + isa_bit); /* Calculate the address of the .got.plt entry. */ - got_address = (htab->sgotplt->output_section->vma - + htab->sgotplt->output_offset + got_address = (htab->root.sgotplt->output_section->vma + + htab->root.sgotplt->output_offset + got_index * MIPS_ELF_GOT_SIZE (dynobj)); got_address_high = ((got_address + 0x8000) >> 16) & 0xffff; got_address_low = got_address & 0xffff; /* Initially point the .got.plt entry at the PLT header. */ - loc = (htab->sgotplt->contents + got_index * MIPS_ELF_GOT_SIZE (dynobj)); + loc = (htab->root.sgotplt->contents + got_index * MIPS_ELF_GOT_SIZE (dynobj)); if (ABI_64_P (output_bfd)) bfd_put_64 (output_bfd, header_address, loc); else bfd_put_32 (output_bfd, header_address, loc); /* Now handle the PLT itself. First the standard entry (the order - does not matter, we just have to pick one). */ + does not matter, we just have to pick one). */ if (h->plt.plist->mips_offset != MINUS_ONE) { const bfd_vma *plt_entry; @@ -10539,10 +10610,10 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, plt_offset = htab->plt_header_size + h->plt.plist->mips_offset; - BFD_ASSERT (plt_offset <= htab->splt->size); + BFD_ASSERT (plt_offset <= htab->root.splt->size); /* Find out where the .plt entry should go. */ - loc = htab->splt->contents + plt_offset; + loc = htab->root.splt->contents + plt_offset; /* Pick the load opcode. */ load = MIPS_ELF_LOAD_WORD (output_bfd); @@ -10578,10 +10649,10 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, plt_offset = (htab->plt_header_size + htab->plt_mips_offset + h->plt.plist->comp_offset); - BFD_ASSERT (plt_offset <= htab->splt->size); + BFD_ASSERT (plt_offset <= htab->root.splt->size); /* Find out where the .plt entry should go. */ - loc = htab->splt->contents + plt_offset; + loc = htab->root.splt->contents + plt_offset; /* Fill in the PLT entry itself. */ if (!MICROMIPS_P (output_bfd)) @@ -10617,20 +10688,21 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT (got_address % 4 == 0); - loc_address = (htab->splt->output_section->vma - + htab->splt->output_offset + plt_offset); + loc_address = (htab->root.splt->output_section->vma + + htab->root.splt->output_offset + plt_offset); gotpc_offset = got_address - ((loc_address | 3) ^ 3); /* ADDIUPC has a span of +/-16MB, check we're in range. */ if (gotpc_offset + 0x1000000 >= 0x2000000) { - (*_bfd_error_handler) - (_("%B: `%A' offset of %ld from `%A' " + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: `%pA' offset of %" PRId64 " from `%pA' " "beyond the range of ADDIUPC"), output_bfd, - htab->sgotplt->output_section, - htab->splt->output_section, - (long) gotpc_offset); + htab->root.sgotplt->output_section, + (int64_t) gotpc_offset, + htab->root.splt->output_section); bfd_set_error (bfd_error_no_error); return FALSE; } @@ -10645,7 +10717,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, } /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */ - mips_elf_output_dynamic_relocation (output_bfd, htab->srelplt, + mips_elf_output_dynamic_relocation (output_bfd, htab->root.srelplt, got_index - 2, h->dynindx, R_MIPS_JUMP_SLOT, got_address); @@ -10809,7 +10881,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT (h->dynindx != -1 || h->forced_local); - sgot = htab->sgot; + sgot = htab->root.sgot; g = htab->got_info; BFD_ASSERT (g != NULL); @@ -10845,7 +10917,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, &e))) { offset = p->gotidx; - BFD_ASSERT (offset > 0 && offset < htab->sgot->size); + BFD_ASSERT (offset > 0 && offset < htab->root.sgot->size); if (bfd_link_pic (info) || (elf_hash_table (info)->dynamic_sections_created && p->d.h != NULL @@ -10992,18 +11064,18 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, gotplt_index = h->plt.plist->gotplt_index; BFD_ASSERT (h->dynindx != -1); - BFD_ASSERT (htab->splt != NULL); + BFD_ASSERT (htab->root.splt != NULL); BFD_ASSERT (gotplt_index != MINUS_ONE); - BFD_ASSERT (plt_offset <= htab->splt->size); + BFD_ASSERT (plt_offset <= htab->root.splt->size); /* Calculate the address of the .plt entry. */ - plt_address = (htab->splt->output_section->vma - + htab->splt->output_offset + plt_address = (htab->root.splt->output_section->vma + + htab->root.splt->output_offset + plt_offset); /* Calculate the address of the .got.plt entry. */ - got_address = (htab->sgotplt->output_section->vma - + htab->sgotplt->output_offset + got_address = (htab->root.sgotplt->output_section->vma + + htab->root.sgotplt->output_offset + gotplt_index * MIPS_ELF_GOT_SIZE (output_bfd)); /* Calculate the offset of the .got.plt entry from @@ -11016,11 +11088,11 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, /* Fill in the initial value of the .got.plt entry. */ bfd_put_32 (output_bfd, plt_address, - (htab->sgotplt->contents + (htab->root.sgotplt->contents + gotplt_index * MIPS_ELF_GOT_SIZE (output_bfd))); /* Find out where the .plt entry should go. */ - loc = htab->splt->contents + plt_offset; + loc = htab->root.splt->contents + plt_offset; if (bfd_link_pic (info)) { @@ -11069,7 +11141,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, } /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */ - loc = (htab->srelplt->contents + loc = (htab->root.srelplt->contents + gotplt_index * sizeof (Elf32_External_Rela)); rel.r_offset = got_address; rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT); @@ -11082,7 +11154,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT (h->dynindx != -1 || h->forced_local); - sgot = htab->sgot; + sgot = htab->root.sgot; g = htab->got_info; BFD_ASSERT (g != NULL); @@ -11113,6 +11185,8 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, if (h->needs_copy) { Elf_Internal_Rela rel; + asection *srel; + bfd_byte *loc; BFD_ASSERT (h->dynindx != -1); @@ -11121,11 +11195,13 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.value); rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY); rel.r_addend = 0; - bfd_elf32_swap_reloca_out (output_bfd, &rel, - htab->srelbss->contents - + (htab->srelbss->reloc_count - * sizeof (Elf32_External_Rela))); - ++htab->srelbss->reloc_count; + if (h->root.u.def.section == htab->root.sdynrelro) + srel = htab->root.sreldynrelro; + else + srel = htab->root.srelbss; + loc = srel->contents + srel->reloc_count * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + ++srel->reloc_count; } /* If this is a mips16/microMIPS symbol, force the value to be even. */ @@ -11160,8 +11236,8 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) plt_entry = micromips_o32_exec_plt0_entry; /* Calculate the value of .got.plt. */ - gotplt_value = (htab->sgotplt->output_section->vma - + htab->sgotplt->output_offset); + gotplt_value = (htab->root.sgotplt->output_section->vma + + htab->root.sgotplt->output_offset); gotplt_value_high = ((gotplt_value + 0x8000) >> 16) & 0xffff; gotplt_value_low = gotplt_value & 0xffff; @@ -11171,7 +11247,7 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) || ~(gotplt_value | 0x7fffffff) == 0); /* Install the PLT header. */ - loc = htab->splt->contents; + loc = htab->root.splt->contents; if (plt_entry == micromips_o32_exec_plt0_entry) { bfd_vma gotpc_offset; @@ -11180,19 +11256,21 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) BFD_ASSERT (gotplt_value % 4 == 0); - loc_address = (htab->splt->output_section->vma - + htab->splt->output_offset); + loc_address = (htab->root.splt->output_section->vma + + htab->root.splt->output_offset); gotpc_offset = gotplt_value - ((loc_address | 3) ^ 3); /* ADDIUPC has a span of +/-16MB, check we're in range. */ if (gotpc_offset + 0x1000000 >= 0x2000000) { - (*_bfd_error_handler) - (_("%B: `%A' offset of %ld from `%A' beyond the range of ADDIUPC"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: `%pA' offset of %" PRId64 " from `%pA' " + "beyond the range of ADDIUPC"), output_bfd, - htab->sgotplt->output_section, - htab->splt->output_section, - (long) gotpc_offset); + htab->root.sgotplt->output_section, + (int64_t) gotpc_offset, + htab->root.splt->output_section); bfd_set_error (bfd_error_no_error); return FALSE; } @@ -11256,10 +11334,11 @@ mips_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) got_value_low = got_value & 0xffff; /* Calculate the address of the PLT header. */ - plt_address = htab->splt->output_section->vma + htab->splt->output_offset; + plt_address = (htab->root.splt->output_section->vma + + htab->root.splt->output_offset); /* Install the PLT header. */ - loc = htab->splt->contents; + loc = htab->root.splt->contents; bfd_put_32 (output_bfd, plt_entry[0] | got_value_high, loc); bfd_put_32 (output_bfd, plt_entry[1] | got_value_low, loc + 4); bfd_put_32 (output_bfd, plt_entry[2], loc + 8); @@ -11320,7 +11399,7 @@ mips_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info) /* We just need to copy the entry byte-by-byte. */ for (i = 0; i < ARRAY_SIZE (mips_vxworks_shared_plt0_entry); i++) bfd_put_32 (output_bfd, mips_vxworks_shared_plt0_entry[i], - htab->splt->contents + i * 4); + htab->root.splt->contents + i * 4); } /* Finish up the dynamic sections. */ @@ -11342,7 +11421,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, sdyn = bfd_get_linker_section (dynobj, ".dynamic"); - sgot = htab->sgot; + sgot = htab->root.sgot; gg = htab->got_info; if (elf_hash_table (info)->dynamic_sections_created) @@ -11390,12 +11469,12 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, break; case DT_PLTGOT: - s = htab->sgot; + s = htab->root.sgot; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_MIPS_PLTGOT: - s = htab->sgotplt; + s = htab->root.sgotplt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; @@ -11450,12 +11529,13 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, } /* In case if we don't have global got symbols we default to setting DT_MIPS_GOTSYM to the same value as - DT_MIPS_SYMTABNO, so we just fall through. */ + DT_MIPS_SYMTABNO. */ + /* Fall through. */ case DT_MIPS_SYMTABNO: name = ".dynsym"; elemsize = MIPS_ELF_SYM_SIZE (output_bfd); - s = bfd_get_section_by_name (output_bfd, name); + s = bfd_get_linker_section (dynobj, name); if (s != NULL) dyn.d_un.d_val = s->size / elemsize; @@ -11515,13 +11595,6 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, dyn.d_un.d_ptr = s->vma; break; - case DT_RELASZ: - BFD_ASSERT (htab->is_vxworks); - /* The count does not include the JUMP_SLOT relocations. */ - if (htab->srelplt) - dyn.d_un.d_val -= htab->srelplt->size; - break; - case DT_PLTREL: BFD_ASSERT (htab->use_plts_and_copy_relocs); if (htab->is_vxworks) @@ -11532,13 +11605,13 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, case DT_PLTRELSZ: BFD_ASSERT (htab->use_plts_and_copy_relocs); - dyn.d_un.d_val = htab->srelplt->size; + dyn.d_un.d_val = htab->root.srelplt->size; break; case DT_JMPREL: BFD_ASSERT (htab->use_plts_and_copy_relocs); - dyn.d_un.d_ptr = (htab->srelplt->output_section->vma - + htab->srelplt->output_offset); + dyn.d_un.d_ptr = (htab->root.srelplt->output_section->vma + + htab->root.srelplt->output_offset); break; case DT_TEXTREL: @@ -11769,7 +11842,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, } } - if (htab->splt && htab->splt->size > 0) + if (htab->root.splt && htab->root.splt->size > 0) { if (htab->is_vxworks) { @@ -11811,6 +11884,10 @@ mips_set_isa_flags (bfd *abfd) val = E_MIPS_ARCH_2; break; + case bfd_mach_mips4010: + val = E_MIPS_ARCH_2 | E_MIPS_MACH_4010; + break; + case bfd_mach_mips4000: case bfd_mach_mips4300: case bfd_mach_mips4400: @@ -11818,10 +11895,6 @@ mips_set_isa_flags (bfd *abfd) val = E_MIPS_ARCH_3; break; - case bfd_mach_mips4010: - val = E_MIPS_ARCH_3 | E_MIPS_MACH_4010; - break; - case bfd_mach_mips4100: val = E_MIPS_ARCH_3 | E_MIPS_MACH_4100; break; @@ -11915,6 +11988,10 @@ mips_set_isa_flags (bfd *abfd) val = E_MIPS_ARCH_32R2; break; + case bfd_mach_mips_interaptiv_mr2: + val = E_MIPS_ARCH_32R2 | E_MIPS_MACH_IAMR2; + break; + case bfd_mach_mipsisa64r2: case bfd_mach_mipsisa64r3: case bfd_mach_mipsisa64r5: @@ -12369,82 +12446,22 @@ _bfd_mips_elf_gc_mark_hook (asection *sec, return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } -/* Update the got entry reference counts for the section being removed. */ +/* Prevent .MIPS.abiflags from being discarded with --gc-sections. */ bfd_boolean -_bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info ATTRIBUTE_UNUSED, - asection *sec ATTRIBUTE_UNUSED, - const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED) +_bfd_mips_elf_gc_mark_extra_sections (struct bfd_link_info *info, + elf_gc_mark_hook_fn gc_mark_hook) { -#if 0 - Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes; - bfd_signed_vma *local_got_refcounts; - const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - struct elf_link_hash_entry *h; + bfd *sub; - if (bfd_link_relocatable (info)) - return TRUE; + _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook); - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - sym_hashes = elf_sym_hashes (abfd); - local_got_refcounts = elf_local_got_refcounts (abfd); + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) + { + asection *o; - relend = relocs + sec->reloc_count; - for (rel = relocs; rel < relend; rel++) - switch (ELF_R_TYPE (abfd, rel->r_info)) - { - case R_MIPS16_GOT16: - case R_MIPS16_CALL16: - case R_MIPS_GOT16: - case R_MIPS_CALL16: - case R_MIPS_CALL_HI16: - case R_MIPS_CALL_LO16: - case R_MIPS_GOT_HI16: - case R_MIPS_GOT_LO16: - case R_MIPS_GOT_DISP: - case R_MIPS_GOT_PAGE: - case R_MIPS_GOT_OFST: - case R_MICROMIPS_GOT16: - case R_MICROMIPS_CALL16: - case R_MICROMIPS_CALL_HI16: - case R_MICROMIPS_CALL_LO16: - case R_MICROMIPS_GOT_HI16: - case R_MICROMIPS_GOT_LO16: - case R_MICROMIPS_GOT_DISP: - case R_MICROMIPS_GOT_PAGE: - case R_MICROMIPS_GOT_OFST: - /* ??? It would seem that the existing MIPS code does no sort - of reference counting or whatnot on its GOT and PLT entries, - so it is not possible to garbage collect them at this time. */ - break; - - default: - break; - } -#endif - - return TRUE; -} - -/* Prevent .MIPS.abiflags from being discarded with --gc-sections. */ - -bfd_boolean -_bfd_mips_elf_gc_mark_extra_sections (struct bfd_link_info *info, - elf_gc_mark_hook_fn gc_mark_hook) -{ - bfd *sub; - - _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook); - - for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) - { - asection *o; - - if (! is_mips_elf (sub)) - continue; + if (! is_mips_elf (sub)) + continue; for (o = sub->sections; o != NULL; o = o->next) if (!o->gc_mark @@ -12590,7 +12607,7 @@ _bfd_mips_elf_ignore_discarded_relocs (asection *sec) bfd_boolean _bfd_mips_elf_write_section (bfd *output_bfd, struct bfd_link_info *link_info ATTRIBUTE_UNUSED, - asection *sec, bfd_byte *contents) + asection *sec, bfd_byte *contents) { bfd_byte *to, *from, *end; int i; @@ -12651,13 +12668,29 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols, line_ptr, discriminator_ptr, dwarf_debug_sections, ABI_64_P (abfd) ? 8 : 0, - &elf_tdata (abfd)->dwarf2_find_line_info)) - return TRUE; + &elf_tdata (abfd)->dwarf2_find_line_info) + || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset, + filename_ptr, functionname_ptr, + line_ptr)) + { + /* PR 22789: If the function name or filename was not found through + the debug information, then try an ordinary lookup instead. */ + if ((functionname_ptr != NULL && *functionname_ptr == NULL) + || (filename_ptr != NULL && *filename_ptr == NULL)) + { + /* Do not override already discovered names. */ + if (functionname_ptr != NULL && *functionname_ptr != NULL) + functionname_ptr = NULL; - if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset, - filename_ptr, functionname_ptr, - line_ptr)) - return TRUE; + if (filename_ptr != NULL && *filename_ptr != NULL) + filename_ptr = NULL; + + _bfd_elf_find_function (abfd, symbols, section, offset, + filename_ptr, functionname_ptr); + } + + return TRUE; + } msec = bfd_get_section_by_name (abfd, ".mdebug"); if (msec != NULL) @@ -12715,11 +12748,11 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols, mips_elf_tdata (abfd)->find_line_info = fi; /* Note that we don't bother to ever free this information. - find_nearest_line is either called all the time, as in - objdump -l, so the information should be saved, or it is - rarely called, as in ld error messages, so the memory - wasted is unimportant. Still, it would probably be a - good idea for free_cached_info to throw it away. */ + find_nearest_line is either called all the time, as in + objdump -l, so the information should be saved, or it is + rarely called, as in ld error messages, so the memory + wasted is unimportant. Still, it would probably be a + good idea for free_cached_info to throw it away. */ } if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap, @@ -12916,25 +12949,22 @@ _bfd_elf_mips_get_relocated_section_contents switch (r) { case bfd_reloc_undefined: - if (!((*link_info->callbacks->undefined_symbol) - (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), - input_bfd, input_section, (*parent)->address, TRUE))) - goto error_return; + (*link_info->callbacks->undefined_symbol) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + input_bfd, input_section, (*parent)->address, TRUE); break; case bfd_reloc_dangerous: BFD_ASSERT (error_message != NULL); - if (!((*link_info->callbacks->reloc_dangerous) - (link_info, error_message, input_bfd, input_section, - (*parent)->address))) - goto error_return; + (*link_info->callbacks->reloc_dangerous) + (link_info, error_message, + input_bfd, input_section, (*parent)->address); break; case bfd_reloc_overflow: - if (!((*link_info->callbacks->reloc_overflow) - (link_info, NULL, - bfd_asymbol_name (*(*parent)->sym_ptr_ptr), - (*parent)->howto->name, (*parent)->addend, - input_bfd, input_section, (*parent)->address))) - goto error_return; + (*link_info->callbacks->reloc_overflow) + (link_info, NULL, + bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + (*parent)->howto->name, (*parent)->addend, + input_bfd, input_section, (*parent)->address); break; case bfd_reloc_outofrange: default: @@ -13110,9 +13140,8 @@ static const struct opcode_descriptor bz_insns_16[] = { /* Switch between a 5-bit register index and its 3-bit shorthand. */ -#define BZ16_REG(opcode) ((((((opcode) >> 7) & 7) + 0x1e) & 0x17) + 2) -#define BZ16_REG_FIELD(r) \ - (((2 <= (r) && (r) <= 7) ? (r) : ((r) - 16)) << 7) +#define BZ16_REG(opcode) ((((((opcode) >> 7) & 7) + 0x1e) & 0xf) + 2) +#define BZ16_REG_FIELD(r) (((r) & 7) << 7) /* 32-bit instructions with a delay slot. */ @@ -13428,12 +13457,12 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, int fndopc; /* The number of bytes to delete for relaxation and from where - to delete these bytes starting at irel->r_offset. */ + to delete these bytes starting at irel->r_offset. */ int delcnt = 0; int deloff = 0; /* If this isn't something that can be relaxed, then ignore - this reloc. */ + this reloc. */ if (r_type != R_MICROMIPS_HI16 && r_type != R_MICROMIPS_PC16_S1 && r_type != R_MICROMIPS_26_S1) @@ -13510,12 +13539,12 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, /* For simplicity of coding, we are going to modify the - section contents, the section relocs, and the BFD symbol - table. We must tell the rest of the code not to free up this - information. It would be possible to instead create a table - of changes which have to be made, as is done in coff-mips.c; - that would be more work, but would require less memory when - the linker is run. */ + section contents, the section relocs, and the BFD symbol + table. We must tell the rest of the code not to free up this + information. It would be possible to instead create a table + of changes which have to be made, as is done in coff-mips.c; + that would be more work, but would require less memory when + the linker is run. */ /* Only 32-bit instructions relaxed. */ if (irel->r_offset + 4 > sec->size) @@ -13524,20 +13553,20 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, opcode = bfd_get_micromips_32 (abfd, ptr); /* This is the pc-relative distance from the instruction the - relocation is applied to, to the symbol referred. */ + relocation is applied to, to the symbol referred. */ pcrval = (symval - (sec->output_section->vma + sec->output_offset) - irel->r_offset); /* R_MICROMIPS_HI16 / LUI relaxation to nil, performing relaxation - of corresponding R_MICROMIPS_LO16 to R_MICROMIPS_HI0_LO16 or - R_MICROMIPS_PC23_S2. The R_MICROMIPS_PC23_S2 condition is + of corresponding R_MICROMIPS_LO16 to R_MICROMIPS_HI0_LO16 or + R_MICROMIPS_PC23_S2. The R_MICROMIPS_PC23_S2 condition is - (symval % 4 == 0 && IS_BITSIZE (pcrval, 25)) + (symval % 4 == 0 && IS_BITSIZE (pcrval, 25)) - where pcrval has first to be adjusted to apply against the LO16 - location (we make the adjustment later on, when we have figured - out the offset). */ + where pcrval has first to be adjusted to apply against the LO16 + location (we make the adjustment later on, when we have figured + out the offset). */ if (r_type == R_MICROMIPS_HI16 && MATCH (opcode, lui_insn)) { bfd_boolean bzc = FALSE; @@ -13621,8 +13650,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, irel[1].r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_HI0_LO16); /* Instructions using R_MICROMIPS_LO16 have the base or - source register in bits 20:16. This register becomes $0 - (zero) as the result of the R_MICROMIPS_HI16 being 0. */ + source register in bits 20:16. This register becomes $0 + (zero) as the result of the R_MICROMIPS_HI16 being 0. */ nextopc &= ~0x001f0000; bfd_put_16 (abfd, (nextopc >> 16) & 0xffff, contents + irel[1].r_offset); @@ -13661,9 +13690,9 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, } /* Compact branch relaxation -- due to the multitude of macros - employed by the compiler/assembler, compact branches are not - always generated. Obviously, this can/will be fixed elsewhere, - but there is no drawback in double checking it here. */ + employed by the compiler/assembler, compact branches are not + always generated. Obviously, this can/will be fixed elsewhere, + but there is no drawback in double checking it here. */ else if (r_type == R_MICROMIPS_PC16_S1 && irel->r_offset + 5 < sec->size && ((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0 @@ -13693,7 +13722,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, } /* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC10_S1. We need - to check the distance from the next instruction, so subtract 2. */ + to check the distance from the next instruction, so subtract 2. */ else if (!insn32 && r_type == R_MICROMIPS_PC16_S1 && IS_BITSIZE (pcrval - 2, 11) @@ -13714,7 +13743,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, } /* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC7_S1. We need - to check the distance from the next instruction, so subtract 2. */ + to check the distance from the next instruction, so subtract 2. */ else if (!insn32 && r_type == R_MICROMIPS_PC16_S1 && IS_BITSIZE (pcrval - 2, 8) @@ -13778,7 +13807,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, if (relaxed) { /* JAL with 32-bit delay slot that is changed to a JALS - with 16-bit delay slot. */ + with 16-bit delay slot. */ bfd_put_micromips_32 (abfd, jal_insn_32_bd16.match, ptr); /* Delete 2 bytes from irel->r_offset + 6. */ @@ -13904,12 +13933,15 @@ _bfd_mips_elf_use_plts_and_copy_relocs (struct bfd_link_info *info) } /* A function that the linker calls to select between all or only - 32-bit microMIPS instructions. */ + 32-bit microMIPS instructions, and between making or ignoring + branch relocation checks for invalid transitions between ISA modes. */ void -_bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on) +_bfd_mips_elf_linker_flags (struct bfd_link_info *info, bfd_boolean insn32, + bfd_boolean ignore_branch_isa) { - mips_elf_hash_table (info)->insn32 = on; + mips_elf_hash_table (info)->insn32 = insn32; + mips_elf_hash_table (info)->ignore_branch_isa = ignore_branch_isa; } /* Structure for saying that BFD machine EXTENSION extends BASE. */ @@ -13973,15 +14005,21 @@ static const struct mips_mach_extension mips_mach_extensions[] = { bfd_mach_mips4400, bfd_mach_mips4000 }, { bfd_mach_mips4300, bfd_mach_mips4000 }, { bfd_mach_mips4100, bfd_mach_mips4000 }, - { bfd_mach_mips4010, bfd_mach_mips4000 }, { bfd_mach_mips5900, bfd_mach_mips4000 }, + /* MIPS32r3 extensions. */ + { bfd_mach_mips_interaptiv_mr2, bfd_mach_mipsisa32r3 }, + + /* MIPS32r2 extensions. */ + { bfd_mach_mipsisa32r3, bfd_mach_mipsisa32r2 }, + /* MIPS32 extensions. */ { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 }, /* MIPS II extensions. */ { bfd_mach_mips4000, bfd_mach_mips6000 }, { bfd_mach_mipsisa32, bfd_mach_mips6000 }, + { bfd_mach_mips4010, bfd_mach_mips6000 }, /* MIPS I extensions. */ { bfd_mach_mips6000, bfd_mach_mips3000 }, @@ -14024,25 +14062,25 @@ bfd_mips_isa_ext_mach (unsigned int isa_ext) { switch (isa_ext) { - case AFL_EXT_3900: return bfd_mach_mips3900; - case AFL_EXT_4010: return bfd_mach_mips4010; - case AFL_EXT_4100: return bfd_mach_mips4100; - case AFL_EXT_4111: return bfd_mach_mips4111; - case AFL_EXT_4120: return bfd_mach_mips4120; - case AFL_EXT_4650: return bfd_mach_mips4650; - case AFL_EXT_5400: return bfd_mach_mips5400; - case AFL_EXT_5500: return bfd_mach_mips5500; - case AFL_EXT_5900: return bfd_mach_mips5900; - case AFL_EXT_10000: return bfd_mach_mips10000; + case AFL_EXT_3900: return bfd_mach_mips3900; + case AFL_EXT_4010: return bfd_mach_mips4010; + case AFL_EXT_4100: return bfd_mach_mips4100; + case AFL_EXT_4111: return bfd_mach_mips4111; + case AFL_EXT_4120: return bfd_mach_mips4120; + case AFL_EXT_4650: return bfd_mach_mips4650; + case AFL_EXT_5400: return bfd_mach_mips5400; + case AFL_EXT_5500: return bfd_mach_mips5500; + case AFL_EXT_5900: return bfd_mach_mips5900; + case AFL_EXT_10000: return bfd_mach_mips10000; case AFL_EXT_LOONGSON_2E: return bfd_mach_mips_loongson_2e; case AFL_EXT_LOONGSON_2F: return bfd_mach_mips_loongson_2f; case AFL_EXT_LOONGSON_3A: return bfd_mach_mips_loongson_3a; - case AFL_EXT_SB1: return bfd_mach_mips_sb1; + case AFL_EXT_SB1: return bfd_mach_mips_sb1; case AFL_EXT_OCTEON: return bfd_mach_mips_octeon; case AFL_EXT_OCTEONP: return bfd_mach_mips_octeonp; case AFL_EXT_OCTEON2: return bfd_mach_mips_octeon2; - case AFL_EXT_XLR: return bfd_mach_mips_xlr; - default: return bfd_mach_mips3000; + case AFL_EXT_XLR: return bfd_mach_mips_xlr; + default: return bfd_mach_mips3000; } } @@ -14053,26 +14091,28 @@ bfd_mips_isa_ext (bfd *abfd) { switch (bfd_get_mach (abfd)) { - case bfd_mach_mips3900: return AFL_EXT_3900; - case bfd_mach_mips4010: return AFL_EXT_4010; - case bfd_mach_mips4100: return AFL_EXT_4100; - case bfd_mach_mips4111: return AFL_EXT_4111; - case bfd_mach_mips4120: return AFL_EXT_4120; - case bfd_mach_mips4650: return AFL_EXT_4650; - case bfd_mach_mips5400: return AFL_EXT_5400; - case bfd_mach_mips5500: return AFL_EXT_5500; - case bfd_mach_mips5900: return AFL_EXT_5900; - case bfd_mach_mips10000: return AFL_EXT_10000; + case bfd_mach_mips3900: return AFL_EXT_3900; + case bfd_mach_mips4010: return AFL_EXT_4010; + case bfd_mach_mips4100: return AFL_EXT_4100; + case bfd_mach_mips4111: return AFL_EXT_4111; + case bfd_mach_mips4120: return AFL_EXT_4120; + case bfd_mach_mips4650: return AFL_EXT_4650; + case bfd_mach_mips5400: return AFL_EXT_5400; + case bfd_mach_mips5500: return AFL_EXT_5500; + case bfd_mach_mips5900: return AFL_EXT_5900; + case bfd_mach_mips10000: return AFL_EXT_10000; case bfd_mach_mips_loongson_2e: return AFL_EXT_LOONGSON_2E; case bfd_mach_mips_loongson_2f: return AFL_EXT_LOONGSON_2F; case bfd_mach_mips_loongson_3a: return AFL_EXT_LOONGSON_3A; - case bfd_mach_mips_sb1: return AFL_EXT_SB1; - case bfd_mach_mips_octeon: return AFL_EXT_OCTEON; - case bfd_mach_mips_octeonp: return AFL_EXT_OCTEONP; - case bfd_mach_mips_octeon3: return AFL_EXT_OCTEON3; - case bfd_mach_mips_octeon2: return AFL_EXT_OCTEON2; - case bfd_mach_mips_xlr: return AFL_EXT_XLR; - default: return 0; + case bfd_mach_mips_sb1: return AFL_EXT_SB1; + case bfd_mach_mips_octeon: return AFL_EXT_OCTEON; + case bfd_mach_mips_octeonp: return AFL_EXT_OCTEONP; + case bfd_mach_mips_octeon3: return AFL_EXT_OCTEON3; + case bfd_mach_mips_octeon2: return AFL_EXT_OCTEON2; + case bfd_mach_mips_xlr: return AFL_EXT_XLR; + case bfd_mach_mips_interaptiv_mr2: + return AFL_EXT_INTERAPTIV_MR2; + default: return 0; } } @@ -14103,8 +14143,9 @@ update_mips_abiflags_isa (bfd *abfd, Elf_Internal_ABIFlags_v0 *abiflags) case E_MIPS_ARCH_64R2: new_isa = LEVEL_REV (64, 2); break; case E_MIPS_ARCH_64R6: new_isa = LEVEL_REV (64, 6); break; default: - (*_bfd_error_handler) - (_("%B: Unknown architecture %s"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: Unknown architecture %s"), abfd, bfd_printable_name (abfd)); } @@ -14217,11 +14258,11 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) scRData, scSData, scSBss, scBss }; - /* Sort the dynamic symbols so that those with GOT entries come after - those without. */ htab = mips_elf_hash_table (info); BFD_ASSERT (htab != NULL); + /* Sort the dynamic symbols so that those with GOT entries come after + those without. */ if (!mips_elf_sort_hash_table (abfd, info)) return FALSE; @@ -14351,7 +14392,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) reginfo.ri_cprmask[3] |= sub.ri_cprmask[3]; /* ri_gp_value is set by the function - mips_elf32_section_processing when the section is + `_bfd_mips_elf_section_processing' when the section is finally written out. */ /* Hack: reset the SEC_HAS_CONTENTS flag so that @@ -14360,7 +14401,16 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) } /* Size has been set in _bfd_mips_elf_always_size_sections. */ - BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo)); + if (o->size != sizeof (Elf32_External_RegInfo)) + { + _bfd_error_handler + (_("%pB: .reginfo section size should be %ld bytes, " + "actual size is %" PRId64), + abfd, (unsigned long) sizeof (Elf32_External_RegInfo), + (int64_t) o->size); + + return FALSE; + } /* Skip this section later on (I don't think this currently matters, but someday it might). */ @@ -14632,9 +14682,9 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) gptab_bss_sec = o; else { - (*_bfd_error_handler) - (_("%s: illegal section name `%s'"), - bfd_get_filename (abfd), o->name); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: illegal section name `%pA'"), abfd, o); bfd_set_error (bfd_error_nonrepresentable_section); return FALSE; } @@ -14867,11 +14917,211 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) return TRUE; } +/* Merge object file header flags from IBFD into OBFD. Raise an error + if there are conflicting settings. */ + +static bfd_boolean +mips_elf_merge_obj_e_flags (bfd *ibfd, struct bfd_link_info *info) +{ + bfd *obfd = info->output_bfd; + struct mips_elf_obj_tdata *out_tdata = mips_elf_tdata (obfd); + flagword old_flags; + flagword new_flags; + bfd_boolean ok; + + new_flags = elf_elfheader (ibfd)->e_flags; + elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER; + old_flags = elf_elfheader (obfd)->e_flags; + + /* Check flag compatibility. */ + + new_flags &= ~EF_MIPS_NOREORDER; + old_flags &= ~EF_MIPS_NOREORDER; + + /* Some IRIX 6 BSD-compatibility objects have this bit set. It + doesn't seem to matter. */ + new_flags &= ~EF_MIPS_XGOT; + old_flags &= ~EF_MIPS_XGOT; + + /* MIPSpro generates ucode info in n64 objects. Again, we should + just be able to ignore this. */ + new_flags &= ~EF_MIPS_UCODE; + old_flags &= ~EF_MIPS_UCODE; + + /* DSOs should only be linked with CPIC code. */ + if ((ibfd->flags & DYNAMIC) != 0) + new_flags |= EF_MIPS_PIC | EF_MIPS_CPIC; + + if (new_flags == old_flags) + return TRUE; + + ok = TRUE; + + if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0) + != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)) + { + _bfd_error_handler + (_("%pB: warning: linking abicalls files with non-abicalls files"), + ibfd); + ok = TRUE; + } + + if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) + elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC; + if (! (new_flags & EF_MIPS_PIC)) + elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC; + + new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC); + old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC); + + /* Compare the ISAs. */ + if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags)) + { + _bfd_error_handler + (_("%pB: linking 32-bit code with 64-bit code"), + ibfd); + ok = FALSE; + } + else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd))) + { + /* OBFD's ISA isn't the same as, or an extension of, IBFD's. */ + if (mips_mach_extends_p (bfd_get_mach (obfd), bfd_get_mach (ibfd))) + { + /* Copy the architecture info from IBFD to OBFD. Also copy + the 32-bit flag (if set) so that we continue to recognise + OBFD as a 32-bit binary. */ + bfd_set_arch_info (obfd, bfd_get_arch_info (ibfd)); + elf_elfheader (obfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH); + elf_elfheader (obfd)->e_flags + |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE); + + /* Update the ABI flags isa_level, isa_rev, isa_ext fields. */ + update_mips_abiflags_isa (obfd, &out_tdata->abiflags); + + /* Copy across the ABI flags if OBFD doesn't use them + and if that was what caused us to treat IBFD as 32-bit. */ + if ((old_flags & EF_MIPS_ABI) == 0 + && mips_32bit_flags_p (new_flags) + && !mips_32bit_flags_p (new_flags & ~EF_MIPS_ABI)) + elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ABI; + } + else + { + /* The ISAs aren't compatible. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: linking %s module with previous %s modules"), + ibfd, + bfd_printable_name (ibfd), + bfd_printable_name (obfd)); + ok = FALSE; + } + } + + new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE); + old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE); + + /* Compare ABIs. The 64-bit ABI does not use EF_MIPS_ABI. But, it + does set EI_CLASS differently from any 32-bit ABI. */ + if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI) + || (elf_elfheader (ibfd)->e_ident[EI_CLASS] + != elf_elfheader (obfd)->e_ident[EI_CLASS])) + { + /* Only error if both are set (to different values). */ + if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI)) + || (elf_elfheader (ibfd)->e_ident[EI_CLASS] + != elf_elfheader (obfd)->e_ident[EI_CLASS])) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: ABI mismatch: linking %s module with previous %s modules"), + ibfd, + elf_mips_abi_name (ibfd), + elf_mips_abi_name (obfd)); + ok = FALSE; + } + new_flags &= ~EF_MIPS_ABI; + old_flags &= ~EF_MIPS_ABI; + } + + /* Compare ASEs. Forbid linking MIPS16 and microMIPS ASE modules together + and allow arbitrary mixing of the remaining ASEs (retain the union). */ + if ((new_flags & EF_MIPS_ARCH_ASE) != (old_flags & EF_MIPS_ARCH_ASE)) + { + int old_micro = old_flags & EF_MIPS_ARCH_ASE_MICROMIPS; + int new_micro = new_flags & EF_MIPS_ARCH_ASE_MICROMIPS; + int old_m16 = old_flags & EF_MIPS_ARCH_ASE_M16; + int new_m16 = new_flags & EF_MIPS_ARCH_ASE_M16; + int micro_mis = old_m16 && new_micro; + int m16_mis = old_micro && new_m16; + + if (m16_mis || micro_mis) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: ASE mismatch: linking %s module with previous %s modules"), + ibfd, + m16_mis ? "MIPS16" : "microMIPS", + m16_mis ? "microMIPS" : "MIPS16"); + ok = FALSE; + } + + elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ARCH_ASE; + + new_flags &= ~ EF_MIPS_ARCH_ASE; + old_flags &= ~ EF_MIPS_ARCH_ASE; + } + + /* Compare NaN encodings. */ + if ((new_flags & EF_MIPS_NAN2008) != (old_flags & EF_MIPS_NAN2008)) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: linking %s module with previous %s modules"), + ibfd, + (new_flags & EF_MIPS_NAN2008 + ? "-mnan=2008" : "-mnan=legacy"), + (old_flags & EF_MIPS_NAN2008 + ? "-mnan=2008" : "-mnan=legacy")); + ok = FALSE; + new_flags &= ~EF_MIPS_NAN2008; + old_flags &= ~EF_MIPS_NAN2008; + } + + /* Compare FP64 state. */ + if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64)) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: linking %s module with previous %s modules"), + ibfd, + (new_flags & EF_MIPS_FP64 + ? "-mfp64" : "-mfp32"), + (old_flags & EF_MIPS_FP64 + ? "-mfp64" : "-mfp32")); + ok = FALSE; + new_flags &= ~EF_MIPS_FP64; + old_flags &= ~EF_MIPS_FP64; + } + + /* Warn about any other mismatches */ + if (new_flags != old_flags) + { + /* xgettext:c-format */ + _bfd_error_handler + (_("%pB: uses different e_flags (%#x) fields than previous modules " + "(%#x)"), + ibfd, new_flags, old_flags); + ok = FALSE; + } + + return ok; +} + /* Merge object attributes from IBFD into OBFD. Raise an error if there are conflicting attributes. */ static bfd_boolean -mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) +mips_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) { + bfd *obfd = info->output_bfd; obj_attribute *in_attr; obj_attribute *out_attr; bfd *abi_fp_bfd; @@ -14941,20 +15191,23 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) in_string = _bfd_mips_fp_abi_string (in_fp); /* First warn about cases involving unrecognised ABIs. */ if (!out_string && !in_string) + /* xgettext:c-format */ _bfd_error_handler - (_("Warning: %B uses unknown floating point ABI %d " - "(set by %B), %B uses unknown floating point ABI %d"), - obfd, abi_fp_bfd, ibfd, out_fp, in_fp); + (_("Warning: %pB uses unknown floating point ABI %d " + "(set by %pB), %pB uses unknown floating point ABI %d"), + obfd, out_fp, abi_fp_bfd, ibfd, in_fp); else if (!out_string) _bfd_error_handler - (_("Warning: %B uses unknown floating point ABI %d " - "(set by %B), %B uses %s"), - obfd, abi_fp_bfd, ibfd, out_fp, in_string); + /* xgettext:c-format */ + (_("Warning: %pB uses unknown floating point ABI %d " + "(set by %pB), %pB uses %s"), + obfd, out_fp, abi_fp_bfd, ibfd, in_string); else if (!in_string) _bfd_error_handler - (_("Warning: %B uses %s (set by %B), " - "%B uses unknown floating point ABI %d"), - obfd, abi_fp_bfd, ibfd, out_string, in_fp); + /* xgettext:c-format */ + (_("Warning: %pB uses %s (set by %pB), " + "%pB uses unknown floating point ABI %d"), + obfd, out_string, abi_fp_bfd, ibfd, in_fp); else { /* If one of the bfds is soft-float, the other must be @@ -14965,8 +15218,9 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) else if (out_fp == Val_GNU_MIPS_ABI_FP_SOFT) in_string = "-mhard-float"; _bfd_error_handler - (_("Warning: %B uses %s (set by %B), %B uses %s"), - obfd, abi_fp_bfd, ibfd, out_string, in_string); + /* xgettext:c-format */ + (_("Warning: %pB uses %s (set by %pB), %pB uses %s"), + obfd, out_string, abi_fp_bfd, ibfd, in_string); } } } @@ -14983,10 +15237,11 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) { case Val_GNU_MIPS_ABI_MSA_128: _bfd_error_handler - (_("Warning: %B uses %s (set by %B), " - "%B uses unknown MSA ABI %d"), - obfd, abi_msa_bfd, ibfd, - "-mmsa", in_attr[Tag_GNU_MIPS_ABI_MSA].i); + /* xgettext:c-format */ + (_("Warning: %pB uses %s (set by %pB), " + "%pB uses unknown MSA ABI %d"), + obfd, "-mmsa", abi_msa_bfd, + ibfd, in_attr[Tag_GNU_MIPS_ABI_MSA].i); break; default: @@ -14994,26 +15249,57 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) { case Val_GNU_MIPS_ABI_MSA_128: _bfd_error_handler - (_("Warning: %B uses unknown MSA ABI %d " - "(set by %B), %B uses %s"), - obfd, abi_msa_bfd, ibfd, - out_attr[Tag_GNU_MIPS_ABI_MSA].i, "-mmsa"); + /* xgettext:c-format */ + (_("Warning: %pB uses unknown MSA ABI %d " + "(set by %pB), %pB uses %s"), + obfd, out_attr[Tag_GNU_MIPS_ABI_MSA].i, + abi_msa_bfd, ibfd, "-mmsa"); break; default: _bfd_error_handler - (_("Warning: %B uses unknown MSA ABI %d " - "(set by %B), %B uses unknown MSA ABI %d"), - obfd, abi_msa_bfd, ibfd, - out_attr[Tag_GNU_MIPS_ABI_MSA].i, - in_attr[Tag_GNU_MIPS_ABI_MSA].i); + /* xgettext:c-format */ + (_("Warning: %pB uses unknown MSA ABI %d " + "(set by %pB), %pB uses unknown MSA ABI %d"), + obfd, out_attr[Tag_GNU_MIPS_ABI_MSA].i, + abi_msa_bfd, ibfd, in_attr[Tag_GNU_MIPS_ABI_MSA].i); break; } } } /* Merge Tag_compatibility attributes and any common GNU ones. */ - _bfd_elf_merge_object_attributes (ibfd, obfd); + return _bfd_elf_merge_object_attributes (ibfd, info); +} + +/* Merge object ABI flags from IBFD into OBFD. Raise an error if + there are conflicting settings. */ + +static bfd_boolean +mips_elf_merge_obj_abiflags (bfd *ibfd, bfd *obfd) +{ + obj_attribute *out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; + struct mips_elf_obj_tdata *out_tdata = mips_elf_tdata (obfd); + struct mips_elf_obj_tdata *in_tdata = mips_elf_tdata (ibfd); + + /* Update the output abiflags fp_abi using the computed fp_abi. */ + out_tdata->abiflags.fp_abi = out_attr[Tag_GNU_MIPS_ABI_FP].i; + +#define max(a, b) ((a) > (b) ? (a) : (b)) + /* Merge abiflags. */ + out_tdata->abiflags.isa_level = max (out_tdata->abiflags.isa_level, + in_tdata->abiflags.isa_level); + out_tdata->abiflags.isa_rev = max (out_tdata->abiflags.isa_rev, + in_tdata->abiflags.isa_rev); + out_tdata->abiflags.gpr_size = max (out_tdata->abiflags.gpr_size, + in_tdata->abiflags.gpr_size); + out_tdata->abiflags.cpr1_size = max (out_tdata->abiflags.cpr1_size, + in_tdata->abiflags.cpr1_size); + out_tdata->abiflags.cpr2_size = max (out_tdata->abiflags.cpr2_size, + in_tdata->abiflags.cpr2_size); +#undef max + out_tdata->abiflags.ases |= in_tdata->abiflags.ases; + out_tdata->abiflags.flags1 |= in_tdata->abiflags.flags1; return TRUE; } @@ -15022,22 +15308,20 @@ mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) object file when linking. */ bfd_boolean -_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { + bfd *obfd = info->output_bfd; struct mips_elf_obj_tdata *out_tdata; struct mips_elf_obj_tdata *in_tdata; - flagword old_flags; - flagword new_flags; - bfd_boolean ok; bfd_boolean null_input_bfd = TRUE; asection *sec; - obj_attribute *out_attr; + bfd_boolean ok; /* Check if we have the same endianness. */ - if (! _bfd_generic_verify_endian_match (ibfd, obfd)) + if (! _bfd_generic_verify_endian_match (ibfd, info)) { - (*_bfd_error_handler) - (_("%B: endianness incompatible with that of the selected emulation"), + _bfd_error_handler + (_("%pB: endianness incompatible with that of the selected emulation"), ibfd); return FALSE; } @@ -15050,8 +15334,8 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0) { - (*_bfd_error_handler) - (_("%B: ABI is incompatible with that of the selected emulation"), + _bfd_error_handler + (_("%pB: ABI is incompatible with that of the selected emulation"), ibfd); return FALSE; } @@ -15088,44 +15372,44 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) Elf_Internal_ABIFlags_v0 abiflags; /* Set up the FP ABI attribute from the abiflags if it is not already - set. */ + set. */ if (in_attr[Tag_GNU_MIPS_ABI_FP].i == Val_GNU_MIPS_ABI_FP_ANY) - in_attr[Tag_GNU_MIPS_ABI_FP].i = in_tdata->abiflags.fp_abi; + in_attr[Tag_GNU_MIPS_ABI_FP].i = in_tdata->abiflags.fp_abi; infer_mips_abiflags (ibfd, &abiflags); in_abiflags = in_tdata->abiflags; /* It is not possible to infer the correct ISA revision - for R3 or R5 so drop down to R2 for the checks. */ + for R3 or R5 so drop down to R2 for the checks. */ if (in_abiflags.isa_rev == 3 || in_abiflags.isa_rev == 5) in_abiflags.isa_rev = 2; if (LEVEL_REV (in_abiflags.isa_level, in_abiflags.isa_rev) < LEVEL_REV (abiflags.isa_level, abiflags.isa_rev)) - (*_bfd_error_handler) - (_("%B: warning: Inconsistent ISA between e_flags and " + _bfd_error_handler + (_("%pB: warning: Inconsistent ISA between e_flags and " ".MIPS.abiflags"), ibfd); if (abiflags.fp_abi != Val_GNU_MIPS_ABI_FP_ANY && in_abiflags.fp_abi != abiflags.fp_abi) - (*_bfd_error_handler) - (_("%B: warning: Inconsistent FP ABI between .gnu.attributes and " + _bfd_error_handler + (_("%pB: warning: Inconsistent FP ABI between .gnu.attributes and " ".MIPS.abiflags"), ibfd); if ((in_abiflags.ases & abiflags.ases) != abiflags.ases) - (*_bfd_error_handler) - (_("%B: warning: Inconsistent ASEs between e_flags and " + _bfd_error_handler + (_("%pB: warning: Inconsistent ASEs between e_flags and " ".MIPS.abiflags"), ibfd); /* The isa_ext is allowed to be an extension of what can be inferred from e_flags. */ if (!mips_mach_extends_p (bfd_mips_isa_ext_mach (abiflags.isa_ext), bfd_mips_isa_ext_mach (in_abiflags.isa_ext))) - (*_bfd_error_handler) - (_("%B: warning: Inconsistent ISA extensions between e_flags and " + _bfd_error_handler + (_("%pB: warning: Inconsistent ISA extensions between e_flags and " ".MIPS.abiflags"), ibfd); if (in_abiflags.flags2 != 0) - (*_bfd_error_handler) - (_("%B: warning: Unexpected flag in the flags2 field of " + _bfd_error_handler + (_("%pB: warning: Unexpected flag in the flags2 field of " ".MIPS.abiflags (0x%lx)"), ibfd, - (unsigned long) in_abiflags.flags2); + in_abiflags.flags2); } else { @@ -15133,9 +15417,6 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) in_tdata->abiflags_valid = TRUE; } - if (!mips_elf_merge_obj_attributes (ibfd, obfd)) - return FALSE; - if (!out_tdata->abiflags_valid) { /* Copy input abiflags if output abiflags are not already valid. */ @@ -15163,208 +15444,16 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) update_mips_abiflags_isa (obfd, &out_tdata->abiflags); } - return TRUE; - } - - /* Update the output abiflags fp_abi using the computed fp_abi. */ - out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; - out_tdata->abiflags.fp_abi = out_attr[Tag_GNU_MIPS_ABI_FP].i; - -#define max(a,b) ((a) > (b) ? (a) : (b)) - /* Merge abiflags. */ - out_tdata->abiflags.isa_level = max (out_tdata->abiflags.isa_level, - in_tdata->abiflags.isa_level); - out_tdata->abiflags.isa_rev = max (out_tdata->abiflags.isa_rev, - in_tdata->abiflags.isa_rev); - out_tdata->abiflags.gpr_size = max (out_tdata->abiflags.gpr_size, - in_tdata->abiflags.gpr_size); - out_tdata->abiflags.cpr1_size = max (out_tdata->abiflags.cpr1_size, - in_tdata->abiflags.cpr1_size); - out_tdata->abiflags.cpr2_size = max (out_tdata->abiflags.cpr2_size, - in_tdata->abiflags.cpr2_size); -#undef max - out_tdata->abiflags.ases |= in_tdata->abiflags.ases; - out_tdata->abiflags.flags1 |= in_tdata->abiflags.flags1; - - new_flags = elf_elfheader (ibfd)->e_flags; - elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER; - old_flags = elf_elfheader (obfd)->e_flags; - - /* Check flag compatibility. */ - - new_flags &= ~EF_MIPS_NOREORDER; - old_flags &= ~EF_MIPS_NOREORDER; - - /* Some IRIX 6 BSD-compatibility objects have this bit set. It - doesn't seem to matter. */ - new_flags &= ~EF_MIPS_XGOT; - old_flags &= ~EF_MIPS_XGOT; - - /* MIPSpro generates ucode info in n64 objects. Again, we should - just be able to ignore this. */ - new_flags &= ~EF_MIPS_UCODE; - old_flags &= ~EF_MIPS_UCODE; - - /* DSOs should only be linked with CPIC code. */ - if ((ibfd->flags & DYNAMIC) != 0) - new_flags |= EF_MIPS_PIC | EF_MIPS_CPIC; - - if (new_flags == old_flags) - return TRUE; - - ok = TRUE; - - if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0) - != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)) - { - (*_bfd_error_handler) - (_("%B: warning: linking abicalls files with non-abicalls files"), - ibfd); ok = TRUE; } + else + ok = mips_elf_merge_obj_e_flags (ibfd, info); - if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) - elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC; - if (! (new_flags & EF_MIPS_PIC)) - elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC; - - new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC); - old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC); - - /* Compare the ISAs. */ - if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags)) - { - (*_bfd_error_handler) - (_("%B: linking 32-bit code with 64-bit code"), - ibfd); - ok = FALSE; - } - else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd))) - { - /* OBFD's ISA isn't the same as, or an extension of, IBFD's. */ - if (mips_mach_extends_p (bfd_get_mach (obfd), bfd_get_mach (ibfd))) - { - /* Copy the architecture info from IBFD to OBFD. Also copy - the 32-bit flag (if set) so that we continue to recognise - OBFD as a 32-bit binary. */ - bfd_set_arch_info (obfd, bfd_get_arch_info (ibfd)); - elf_elfheader (obfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH); - elf_elfheader (obfd)->e_flags - |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE); - - /* Update the ABI flags isa_level, isa_rev, isa_ext fields. */ - update_mips_abiflags_isa (obfd, &out_tdata->abiflags); - - /* Copy across the ABI flags if OBFD doesn't use them - and if that was what caused us to treat IBFD as 32-bit. */ - if ((old_flags & EF_MIPS_ABI) == 0 - && mips_32bit_flags_p (new_flags) - && !mips_32bit_flags_p (new_flags & ~EF_MIPS_ABI)) - elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ABI; - } - else - { - /* The ISAs aren't compatible. */ - (*_bfd_error_handler) - (_("%B: linking %s module with previous %s modules"), - ibfd, - bfd_printable_name (ibfd), - bfd_printable_name (obfd)); - ok = FALSE; - } - } - - new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE); - old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE); - - /* Compare ABIs. The 64-bit ABI does not use EF_MIPS_ABI. But, it - does set EI_CLASS differently from any 32-bit ABI. */ - if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI) - || (elf_elfheader (ibfd)->e_ident[EI_CLASS] - != elf_elfheader (obfd)->e_ident[EI_CLASS])) - { - /* Only error if both are set (to different values). */ - if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI)) - || (elf_elfheader (ibfd)->e_ident[EI_CLASS] - != elf_elfheader (obfd)->e_ident[EI_CLASS])) - { - (*_bfd_error_handler) - (_("%B: ABI mismatch: linking %s module with previous %s modules"), - ibfd, - elf_mips_abi_name (ibfd), - elf_mips_abi_name (obfd)); - ok = FALSE; - } - new_flags &= ~EF_MIPS_ABI; - old_flags &= ~EF_MIPS_ABI; - } - - /* Compare ASEs. Forbid linking MIPS16 and microMIPS ASE modules together - and allow arbitrary mixing of the remaining ASEs (retain the union). */ - if ((new_flags & EF_MIPS_ARCH_ASE) != (old_flags & EF_MIPS_ARCH_ASE)) - { - int old_micro = old_flags & EF_MIPS_ARCH_ASE_MICROMIPS; - int new_micro = new_flags & EF_MIPS_ARCH_ASE_MICROMIPS; - int old_m16 = old_flags & EF_MIPS_ARCH_ASE_M16; - int new_m16 = new_flags & EF_MIPS_ARCH_ASE_M16; - int micro_mis = old_m16 && new_micro; - int m16_mis = old_micro && new_m16; - - if (m16_mis || micro_mis) - { - (*_bfd_error_handler) - (_("%B: ASE mismatch: linking %s module with previous %s modules"), - ibfd, - m16_mis ? "MIPS16" : "microMIPS", - m16_mis ? "microMIPS" : "MIPS16"); - ok = FALSE; - } - - elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ARCH_ASE; - - new_flags &= ~ EF_MIPS_ARCH_ASE; - old_flags &= ~ EF_MIPS_ARCH_ASE; - } - - /* Compare NaN encodings. */ - if ((new_flags & EF_MIPS_NAN2008) != (old_flags & EF_MIPS_NAN2008)) - { - _bfd_error_handler (_("%B: linking %s module with previous %s modules"), - ibfd, - (new_flags & EF_MIPS_NAN2008 - ? "-mnan=2008" : "-mnan=legacy"), - (old_flags & EF_MIPS_NAN2008 - ? "-mnan=2008" : "-mnan=legacy")); - ok = FALSE; - new_flags &= ~EF_MIPS_NAN2008; - old_flags &= ~EF_MIPS_NAN2008; - } - - /* Compare FP64 state. */ - if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64)) - { - _bfd_error_handler (_("%B: linking %s module with previous %s modules"), - ibfd, - (new_flags & EF_MIPS_FP64 - ? "-mfp64" : "-mfp32"), - (old_flags & EF_MIPS_FP64 - ? "-mfp64" : "-mfp32")); - ok = FALSE; - new_flags &= ~EF_MIPS_FP64; - old_flags &= ~EF_MIPS_FP64; - } + ok = mips_elf_merge_obj_attributes (ibfd, info) && ok; - /* Warn about any other mismatches */ - if (new_flags != old_flags) - { - (*_bfd_error_handler) - (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), - ibfd, (unsigned long) new_flags, - (unsigned long) old_flags); - ok = FALSE; - } + ok = mips_elf_merge_obj_abiflags (ibfd, obfd) && ok; - if (! ok) + if (!ok) { bfd_set_error (bfd_error_bad_value); return FALSE; @@ -15530,6 +15619,8 @@ print_mips_ases (FILE *file, unsigned int mask) fputs ("\n\tDSP ASE", file); if (mask & AFL_ASE_DSPR2) fputs ("\n\tDSP R2 ASE", file); + if (mask & AFL_ASE_DSPR3) + fputs ("\n\tDSP R3 ASE", file); if (mask & AFL_ASE_EVA) fputs ("\n\tEnhanced VA Scheme", file); if (mask & AFL_ASE_MCU) @@ -15552,6 +15643,8 @@ print_mips_ases (FILE *file, unsigned int mask) fputs ("\n\tMICROMIPS ASE", file); if (mask & AFL_ASE_XPA) fputs ("\n\tXPA ASE", file); + if (mask & AFL_ASE_MIPS16E2) + fputs ("\n\tMIPS16e2 ASE", file); if (mask == 0) fprintf (file, "\n\t%s", _("None")); else if ((mask & ~AFL_ASE_MASK) != 0) @@ -15623,6 +15716,9 @@ print_mips_isa_ext (FILE *file, unsigned int isa_ext) case AFL_EXT_LOONGSON_2F: fputs ("ST Microelectronics Loongson 2F", file); break; + case AFL_EXT_INTERAPTIV_MR2: + fputs ("Imagination interAptiv MR2", file); + break; default: fprintf (file, "%s (%d)", _("Unknown"), isa_ext); break; @@ -15795,13 +15891,13 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr) const struct bfd_elf_special_section _bfd_mips_elf_special_sections[] = { - { STRING_COMMA_LEN (".lit4"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, - { STRING_COMMA_LEN (".lit8"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, + { STRING_COMMA_LEN (".lit4"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, + { STRING_COMMA_LEN (".lit8"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, { STRING_COMMA_LEN (".mdebug"), 0, SHT_MIPS_DEBUG, 0 }, - { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, + { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, { STRING_COMMA_LEN (".ucode"), 0, SHT_MIPS_UCODE, 0 }, - { NULL, 0, 0, 0, 0 } + { NULL, 0, 0, 0, 0 } }; /* Merge non visibility st_other attributes. Ensure that the @@ -16095,6 +16191,16 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd, return n; } +/* Return the ABI flags associated with ABFD if available. */ + +Elf_Internal_ABIFlags_v0 * +bfd_mips_elf_get_abiflags (bfd *abfd) +{ + struct mips_elf_obj_tdata *tdata = mips_elf_tdata (abfd); + + return tdata->abiflags_valid ? &tdata->abiflags : NULL; +} + void _bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info) {