X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-microblaze.c;h=caf0f2edcaa2a95c20c038a9b49cec51af22007d;hb=0bff75284e1067e22cbe88fad672362db06f22ee;hp=29fffb4e2c10bac879f66efd030bde5c02fbed0e;hpb=38f14ab8fcfa4eab8bab417a5a165b7403ef9b0e;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c index 29fffb4e2c..caf0f2edca 100644 --- a/bfd/elf32-microblaze.c +++ b/bfd/elf32-microblaze.c @@ -1,6 +1,6 @@ /* Xilinx MicroBlaze-specific support for 32-bit ELF - Copyright (C) 2009-2018 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -251,6 +251,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] = 0x0000ffff, /* Dest Mask. */ TRUE), /* PC relative offset? */ + /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */ + HOWTO (R_MICROBLAZE_TEXTPCREL_64, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain on overflow. */ + bfd_elf_generic_reloc, /* Special Function. */ + "R_MICROBLAZE_TEXTPCREL_64", /* Name. */ + FALSE, /* Partial Inplace. */ + 0, /* Source Mask. */ + 0x0000ffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ + /* A 64 bit GOT relocation. Table-entry not really used. */ HOWTO (R_MICROBLAZE_GOT_64, /* Type. */ 0, /* Rightshift. */ @@ -266,6 +281,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] = 0x0000ffff, /* Dest Mask. */ FALSE), /* PC relative offset? */ + /* A 64 bit TEXTREL relocation. Table-entry not really used. */ + HOWTO (R_MICROBLAZE_TEXTREL_64, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + FALSE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain on overflow. */ + bfd_elf_generic_reloc,/* Special Function. */ + "R_MICROBLAZE_TEXTREL_64",/* Name. */ + FALSE, /* Partial Inplace. */ + 0, /* Source Mask. */ + 0x0000ffff, /* Dest Mask. */ + FALSE), /* PC relative offset? */ + /* A 64 bit PLT relocation. Table-entry not really used. */ HOWTO (R_MICROBLAZE_PLT_64, /* Type. */ 0, /* Rightshift. */ @@ -578,6 +608,12 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, case BFD_RELOC_MICROBLAZE_64_GOT: microblaze_reloc = R_MICROBLAZE_GOT_64; break; + case BFD_RELOC_MICROBLAZE_64_TEXTPCREL: + microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64; + break; + case BFD_RELOC_MICROBLAZE_64_TEXTREL: + microblaze_reloc = R_MICROBLAZE_TEXTREL_64; + break; case BFD_RELOC_MICROBLAZE_64_PLT: microblaze_reloc = R_MICROBLAZE_PLT_64; break; @@ -638,7 +674,7 @@ microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, /* Set the howto pointer for a RCE ELF reloc. */ -static void +static bfd_boolean microblaze_elf_info_to_howto (bfd * abfd, arelent * cache_ptr, Elf_Internal_Rela * dst) @@ -656,10 +692,11 @@ microblaze_elf_info_to_howto (bfd * abfd, _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type); bfd_set_error (bfd_error_bad_value); - r_type = R_MICROBLAZE_NONE; + return FALSE; } cache_ptr->howto = microblaze_elf_howto_table [r_type]; + return TRUE; } /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */ @@ -684,9 +721,6 @@ struct elf32_mb_link_hash_entry { struct elf_link_hash_entry elf; - /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; - /* TLS Reference Types for the symbol; Updated by check_relocs */ #define TLS_GD 1 /* GD reloc. */ #define TLS_LD 2 /* LD reloc. */ @@ -753,7 +787,6 @@ link_hash_newfunc (struct bfd_hash_entry *entry, struct elf32_mb_link_hash_entry *eh; eh = (struct elf32_mb_link_hash_entry *) entry; - eh->dyn_relocs = NULL; eh->tls_mask = 0; } @@ -766,7 +799,7 @@ static struct bfd_link_hash_table * microblaze_elf_link_hash_table_create (bfd *abfd) { struct elf32_mb_link_hash_table *ret; - bfd_size_type amt = sizeof (struct elf32_mb_link_hash_table); + size_t amt = sizeof (struct elf32_mb_link_hash_table); ret = (struct elf32_mb_link_hash_table *) bfd_zmalloc (amt); if (ret == NULL) @@ -1034,7 +1067,7 @@ microblaze_elf_relocate_section (bfd *output_bfd, /* Only relocate if the symbol is defined. */ if (sec) { - name = bfd_get_section_name (sec->owner, sec); + name = bfd_section_name (sec); if (strcmp (name, ".sdata2") == 0 || strcmp (name, ".sbss2") == 0) @@ -1082,7 +1115,7 @@ microblaze_elf_relocate_section (bfd *output_bfd, /* Only relocate if the symbol is defined. */ if (sec) { - name = bfd_get_section_name (sec->owner, sec); + name = bfd_section_name (sec); if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) @@ -1139,6 +1172,18 @@ microblaze_elf_relocate_section (bfd *output_bfd, contents + offset + endian + INST_WORD_SIZE); break; + case (int) R_MICROBLAZE_TEXTPCREL_64: + relocation = input_section->output_section->vma; + relocation -= (input_section->output_section->vma + + input_section->output_offset + + offset + INST_WORD_SIZE); + relocation += addend; + bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff, + contents + offset + endian); + bfd_put_16 (input_bfd, relocation & 0xffff, + contents + offset + endian + INST_WORD_SIZE); + break; + case (int) R_MICROBLAZE_PLT_64: { bfd_vma immediate; @@ -1389,6 +1434,8 @@ microblaze_elf_relocate_section (bfd *output_bfd, bfd_put_16 (input_bfd, relocation & 0xffff, contents + offset + 2 + INST_WORD_SIZE); break; + case (int) R_MICROBLAZE_TEXTREL_64: + case (int) R_MICROBLAZE_TEXTREL_32_LO: case (int) R_MICROBLAZE_64_PCREL : case (int) R_MICROBLAZE_64: case (int) R_MICROBLAZE_32: @@ -1407,11 +1454,22 @@ microblaze_elf_relocate_section (bfd *output_bfd, relocation -= (input_section->output_section->vma + input_section->output_offset + offset + INST_WORD_SIZE); - bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff, + else if (r_type == R_MICROBLAZE_TEXTREL_64 + || r_type == R_MICROBLAZE_TEXTREL_32_LO) + relocation -= input_section->output_section->vma; + + if (r_type == R_MICROBLAZE_TEXTREL_32_LO) + bfd_put_16 (input_bfd, relocation & 0xffff, + contents + offset + endian); + + else + { + bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff, contents + offset + endian); - bfd_put_16 (input_bfd, relocation & 0xffff, + bfd_put_16 (input_bfd, relocation & 0xffff, contents + offset + endian + INST_WORD_SIZE); } + } break; } @@ -1502,11 +1560,24 @@ microblaze_elf_relocate_section (bfd *output_bfd, relocation -= (input_section->output_section->vma + input_section->output_offset + offset + INST_WORD_SIZE); - bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff, - contents + offset + endian); - bfd_put_16 (input_bfd, relocation & 0xffff, - contents + offset + endian + INST_WORD_SIZE); - } + else if (r_type == R_MICROBLAZE_TEXTREL_64 + || r_type == R_MICROBLAZE_TEXTREL_32_LO) + relocation -= input_section->output_section->vma; + + if (r_type == R_MICROBLAZE_TEXTREL_32_LO) + { + bfd_put_16 (input_bfd, relocation & 0xffff, + contents + offset + endian); + } + else + { + bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff, + contents + offset + endian); + bfd_put_16 (input_bfd, relocation & 0xffff, + contents + offset + endian + + INST_WORD_SIZE); + } + } break; } } @@ -1533,7 +1604,7 @@ microblaze_elf_relocate_section (bfd *output_bfd, name = (bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name)); if (name == NULL || *name == '\0') - name = bfd_section_name (input_bfd, sec); + name = bfd_section_name (sec); } if (errmsg != NULL) @@ -1699,7 +1770,8 @@ microblaze_elf_relax_section (bfd *abfd, { bfd_vma symval; if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL) - && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64 )) + && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64) + && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64)) continue; /* Can't delete this reloc. */ /* Get the section contents. */ @@ -1769,6 +1841,10 @@ microblaze_elf_relax_section (bfd *abfd, + sec->output_section->vma + sec->output_offset); } + else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64) + { + symval = symval + irel->r_addend - (sec->output_section->vma); + } else symval += irel->r_addend; @@ -1791,6 +1867,10 @@ microblaze_elf_relax_section (bfd *abfd, irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), (int) R_MICROBLAZE_32_LO); break; + case R_MICROBLAZE_TEXTREL_64: + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + (int) R_MICROBLAZE_TEXTREL_32_LO); + break; default: /* Cannot happen. */ BFD_ASSERT (FALSE); @@ -1817,6 +1897,8 @@ microblaze_elf_relax_section (bfd *abfd, break; case R_MICROBLAZE_64_PCREL: break; + case R_MICROBLAZE_TEXTREL_64: + case R_MICROBLAZE_TEXTREL_32_LO: case R_MICROBLAZE_64: case R_MICROBLAZE_32_LO: /* If this reloc is against a symbol defined in this @@ -1953,7 +2035,10 @@ microblaze_elf_relax_section (bfd *abfd, } } else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO) - || (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_LO)) + || (ELF32_R_TYPE (irelscan->r_info) + == (int) R_MICROBLAZE_32_LO) + || (ELF32_R_TYPE (irelscan->r_info) + == (int) R_MICROBLAZE_TEXTREL_32_LO)) { isym = isymbuf + ELF32_R_SYM (irelscan->r_info); @@ -1997,7 +2082,9 @@ microblaze_elf_relax_section (bfd *abfd, } } - if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64) + if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64 + || (ELF32_R_TYPE (irelscan->r_info) + == (int) R_MICROBLAZE_TEXTREL_64)) { isym = isymbuf + ELF32_R_SYM (irelscan->r_info); @@ -2143,11 +2230,8 @@ microblaze_elf_relax_section (bfd *abfd, symtab_hdr->contents = (bfd_byte *) isymbuf; } - if (free_relocs != NULL) - { - free (free_relocs); - free_relocs = NULL; - } + free (free_relocs); + free_relocs = NULL; if (free_contents != NULL) { @@ -2170,16 +2254,11 @@ microblaze_elf_relax_section (bfd *abfd, return TRUE; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (sec->relax != NULL) - { - free (sec->relax); - sec->relax = NULL; - sec->relax_count = 0; - } + free (free_relocs); + free (free_contents); + free (sec->relax); + sec->relax = NULL; + sec->relax_count = 0; return FALSE; } @@ -2433,7 +2512,7 @@ microblaze_elf_check_relocs (bfd * abfd, /* If this is a global symbol, we count the number of relocations we need for this symbol. */ if (h != NULL) - head = &((struct elf32_mb_link_hash_entry *) h)->dyn_relocs; + head = &h->dyn_relocs; else { /* Track dynamic relocs needed for local syms too. @@ -2460,7 +2539,7 @@ microblaze_elf_check_relocs (bfd * abfd, p = *head; if (p == NULL || p->sec != sec) { - bfd_size_type amt = sizeof *p; + size_t amt = sizeof *p; p = ((struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt)); if (p == NULL) @@ -2496,62 +2575,11 @@ microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info, edir = (struct elf32_mb_link_hash_entry *) dir; eind = (struct elf32_mb_link_hash_entry *) ind; - if (eind->dyn_relocs != NULL) - { - if (edir->dyn_relocs != NULL) - { - struct elf_dyn_relocs **pp; - struct elf_dyn_relocs *p; - - if (ind->root.type == bfd_link_hash_indirect) - abort (); - - /* Add reloc counts against the weak sym to the strong sym - list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) - { - struct elf_dyn_relocs *q; - - for (q = edir->dyn_relocs; q != NULL; q = q->next) - if (q->sec == p->sec) - { - q->pc_count += p->pc_count; - q->count += p->count; - *pp = p->next; - break; - } - if (q == NULL) - pp = &p->next; - } - *pp = edir->dyn_relocs; - } - - edir->dyn_relocs = eind->dyn_relocs; - eind->dyn_relocs = NULL; - } - edir->tls_mask |= eind->tls_mask; _bfd_elf_link_hash_copy_indirect (info, dir, ind); } -/* Find dynamic relocs for H that apply to read-only sections. */ - -static asection * -readonly_dynrelocs (struct elf_link_hash_entry *h) -{ - struct elf_dyn_relocs *p; - - for (p = elf32_mb_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; - - if (s != NULL && (s->flags & SEC_READONLY) != 0) - return p->sec; - } - return NULL; -} - static bfd_boolean microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) @@ -2630,7 +2658,7 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* If we don't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - if (!readonly_dynrelocs (h)) + if (!_bfd_elf_readonly_dynrelocs (h)) { h->non_got_ref = 0; return TRUE; @@ -2675,7 +2703,7 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info, s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); if (power_of_two > s->alignment_power) { - if (!bfd_set_section_alignment (s->owner, s, power_of_two)) + if (!bfd_set_section_alignment (s, power_of_two)) return FALSE; } @@ -2815,7 +2843,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat) else h->got.offset = (bfd_vma) -1; - if (eh->dyn_relocs == NULL) + if (h->dyn_relocs == NULL) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for @@ -2832,7 +2860,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &h->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; @@ -2843,7 +2871,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat) } } else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; } else { @@ -2873,13 +2901,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat) goto keep; } - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; keep: ; } /* Finally, allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; sreloc->size += p->count * sizeof (Elf32_External_Rela); @@ -3024,7 +3052,7 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* It's OK to base decisions on the section name, because none of the dynobj section names depend upon the input files. */ - name = bfd_get_section_name (dynobj, s); + name = bfd_section_name (s); if (strncmp (name, ".rela", 5) == 0) { @@ -3364,9 +3392,10 @@ microblaze_elf_finish_dynamic_sections (bfd *output_bfd, memset (splt->contents, 0, PLT_ENTRY_SIZE); bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop. */, splt->contents + splt->size - 4); - } - elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; + if (splt->output_section != bfd_abs_section_ptr) + elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; + } } /* Set the first entry in the global offset table to the address of @@ -3409,7 +3438,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd, put into .sbss. */ *secp = bfd_make_section_old_way (abfd, ".sbss"); if (*secp == NULL - || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON)) + || !bfd_set_section_flags (*secp, SEC_IS_COMMON)) return FALSE; *valp = sym->st_size;