diff options
Diffstat (limited to 'bfd/elf32-m32r.c')
-rw-r--r-- | bfd/elf32-m32r.c | 205 |
1 files changed, 133 insertions, 72 deletions
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index 21d37b176ce..b7609e02ada 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -669,7 +669,7 @@ static reloc_howto_type m32r_elf_howto_table[] = 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_M32R_RELATIVE", /* name */ + "R_M32R_RELATIVE", /* name */ FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ @@ -678,15 +678,15 @@ static reloc_howto_type m32r_elf_howto_table[] = HOWTO (R_M32R_GOTOFF, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 24, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GOTOFF", /* name */ + "R_M32R_GOTOFF", /* name */ FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* An PC Relative 24-bit relocation used when setting PIC offset @@ -803,6 +803,48 @@ static reloc_howto_type m32r_elf_howto_table[] = 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ TRUE), /* pcrel_offset */ + + HOWTO (R_M32R_GOTOFF_HI_ULO, /* type */ + 16, /* 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_M32R_GOTOFF_HI_ULO",/* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_M32R_GOTOFF_HI_SLO, /* type */ + 16, /* 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_M32R_GOTOFF_HI_SLO",/* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_M32R_GOTOFF_LO, /* 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_M32R_GOTOFF_LO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; /* Handle the R_M32R_10_PCREL reloc. */ @@ -863,7 +905,7 @@ m32r_elf_do_10_pcrel_reloc (abfd, howto, input_section, data, offset, bfd_reloc_status_type status; /* Sanity check the address (offset in section). */ - if (offset > input_section->_cooked_size) + if (offset > bfd_get_section_limit (abfd, input_section)) return bfd_reloc_outofrange; relocation = symbol_value + addend; @@ -942,7 +984,7 @@ m32r_elf_hi16_reloc (abfd, reloc_entry, symbol, data, } /* Sanity check the address (offset in section). */ - if (reloc_entry->address > input_section->_cooked_size) + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) return bfd_reloc_outofrange; ret = bfd_reloc_ok; @@ -1115,7 +1157,7 @@ m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, a section relative addend which is wrong. */ /* Sanity check the address (offset in section). */ - if (reloc_entry->address > input_section->_cooked_size) + if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section)) return bfd_reloc_outofrange; ret = bfd_reloc_ok; @@ -1263,6 +1305,9 @@ static const struct m32r_reloc_map m32r_reloc_map[] = { BFD_RELOC_M32R_GOTPC_HI_ULO, R_M32R_GOTPC_HI_ULO }, { BFD_RELOC_M32R_GOTPC_HI_SLO, R_M32R_GOTPC_HI_SLO }, { BFD_RELOC_M32R_GOTPC_LO, R_M32R_GOTPC_LO }, + { BFD_RELOC_M32R_GOTOFF_HI_ULO, R_M32R_GOTOFF_HI_ULO }, + { BFD_RELOC_M32R_GOTOFF_HI_SLO, R_M32R_GOTOFF_HI_SLO }, + { BFD_RELOC_M32R_GOTOFF_LO, R_M32R_GOTOFF_LO }, }; static reloc_howto_type * @@ -2020,7 +2065,7 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); srel = htab->srelbss; BFD_ASSERT (srel != NULL); - srel->_raw_size += sizeof (Elf32_External_Rela); + srel->size += sizeof (Elf32_External_Rela); h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; } @@ -2031,8 +2076,7 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); power_of_two = 3; /* Apply the required alignment. */ - s->_raw_size = BFD_ALIGN (s->_raw_size, - (bfd_size_type) (1 << power_of_two)); + s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); if (power_of_two > bfd_get_section_alignment (dynobj, s)) { if (! bfd_set_section_alignment (dynobj, s, power_of_two)) @@ -2041,10 +2085,10 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); /* Define the symbol as being at this point in the section. */ h->root.u.def.section = s; - h->root.u.def.value = s->_raw_size; + h->root.u.def.value = s->size; /* Increment the section size to make room for the symbol. */ - s->_raw_size += h->size; + s->size += h->size; return TRUE; } @@ -2104,10 +2148,10 @@ allocate_dynrelocs (h, inf) /* If this is the first .plt entry, make room for the special first entry. */ - if (s->_raw_size == 0) - s->_raw_size += PLT_ENTRY_SIZE; + if (s->size == 0) + s->size += PLT_ENTRY_SIZE; - h->plt.offset = s->_raw_size; + h->plt.offset = s->size; /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this @@ -2122,14 +2166,14 @@ allocate_dynrelocs (h, inf) } /* Make room for this entry. */ - s->_raw_size += PLT_ENTRY_SIZE; + s->size += PLT_ENTRY_SIZE; /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - htab->sgotplt->_raw_size += 4; + htab->sgotplt->size += 4; /* We also need to make an entry in the .rel.plt section. */ - htab->srelplt->_raw_size += sizeof (Elf32_External_Rela); + htab->srelplt->size += sizeof (Elf32_External_Rela); } else { @@ -2159,11 +2203,11 @@ allocate_dynrelocs (h, inf) s = htab->sgot; - h->got.offset = s->_raw_size; - s->_raw_size += 4; + h->got.offset = s->size; + s->size += 4; dyn = htab->root.dynamic_sections_created; if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)) - htab->srelgot->_raw_size += sizeof (Elf32_External_Rela); + htab->srelgot->size += sizeof (Elf32_External_Rela); } else h->got.offset = (bfd_vma) -1; @@ -2232,7 +2276,7 @@ allocate_dynrelocs (h, inf) for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; - sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela); + sreloc->size += p->count * sizeof (Elf32_External_Rela); } return TRUE; @@ -2296,7 +2340,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); { s = bfd_get_section_by_name (dynobj, ".interp"); BFD_ASSERT (s != NULL); - s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; + s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } @@ -2334,7 +2378,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); else if (p->count != 0) { srel = elf_section_data (p->sec)->sreloc; - srel->_raw_size += p->count * sizeof (Elf32_External_Rela); + srel->size += p->count * sizeof (Elf32_External_Rela); if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; } @@ -2354,10 +2398,10 @@ printf("m32r_elf_size_dynamic_sections()\n"); { if (*local_got > 0) { - *local_got = s->_raw_size; - s->_raw_size += 4; + *local_got = s->size; + s->size += 4; if (info->shared) - srel->_raw_size += sizeof (Elf32_External_Rela); + srel->size += sizeof (Elf32_External_Rela); } else *local_got = (bfd_vma) -1; @@ -2385,7 +2429,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); } else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) { - if (s->_raw_size != 0 && s != htab->srelplt) + if (s->size != 0 && s != htab->srelplt) relocs = TRUE; /* We use the reloc_count field as a counter if we need @@ -2398,7 +2442,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); continue; } - if (s->_raw_size == 0) + if (s->size == 0) { /* If we don't need this section, strip it from the output file. This is mostly to handle .rela.bss and @@ -2418,7 +2462,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); section's contents are written out. This should not happen, but this way if it does, we get a R_M32R_NONE reloc instead of garbage. */ - s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); + s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); if (s->contents == NULL) return FALSE; } @@ -2439,7 +2483,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); return FALSE; } - if (htab->splt->_raw_size != 0) + if (htab->splt->size != 0) { if (! add_dynamic_entry (DT_PLTGOT, 0) || ! add_dynamic_entry (DT_PLTRELSZ, 0) @@ -2528,6 +2572,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, bfd *dynobj; bfd_vma *local_got_offsets; asection *sgot, *splt, *sreloc; + bfd_vma high_address = bfd_get_section_limit (input_bfd, input_section); dynobj = htab->root.dynobj; local_got_offsets = elf_local_got_offsets (input_bfd); @@ -2561,8 +2606,8 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, r_type = ELF32_R_TYPE (rel->r_info); if (r_type < 0 || r_type >= (int) R_M32R_max) { - (*_bfd_error_handler) (_("%s: unknown relocation type %d"), - bfd_archive_filename (input_bfd), + (*_bfd_error_handler) (_("%B: unknown relocation type %d"), + input_bfd, (int) r_type); bfd_set_error (bfd_error_bad_value); ret = FALSE; @@ -2582,7 +2627,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, howto = m32r_elf_howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); - if (info->relocatable && (use_rel == TRUE)) + if (info->relocatable && use_rel) { /* This is a relocatable link. We don't have to change anything, unless the reloc is against a section symbol, @@ -2658,7 +2703,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, sec = local_sections[r_symndx]; sym_name = "<local symbol>"; - if (use_rel == FALSE) + if (!use_rel) { relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); addend = rel->r_addend; @@ -2685,7 +2730,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, else { /* External symbol. */ - if (info->relocatable && (use_rel == FALSE)) + if (info->relocatable && !use_rel) continue; h = sym_hashes[r_symndx - symtab_hdr->sh_info]; @@ -2779,7 +2824,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, } /* Sanity check the address. */ - if (offset > input_section->_raw_size) + if (offset > high_address) { r = bfd_reloc_outofrange; goto check_reloc; @@ -2787,6 +2832,31 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, switch ((int) r_type) { + case R_M32R_GOTOFF: + /* Relocation is relative to the start of the global offset + table (for ld24 rx, #uimm24). eg access at label+addend + + ld24 rx. #label@GOTOFF + addend + sub rx, r12. */ + + BFD_ASSERT (sgot != NULL); + + relocation = -(relocation - sgot->output_section->vma); + rel->r_addend = -rel->r_addend; + break; + + case R_M32R_GOTOFF_HI_ULO: + case R_M32R_GOTOFF_HI_SLO: + case R_M32R_GOTOFF_LO: + BFD_ASSERT (sgot != NULL); + + relocation -= sgot->output_section->vma; + + if ((r_type == R_M32R_GOTOFF_HI_SLO) + && ((relocation + rel->r_addend) & 0x8000)) + rel->r_addend += 0x10000; + break; + case R_M32R_GOTPC24: /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation ld24 rx,#_GLOBAL_OFFSET_TABLE_ @@ -2961,7 +3031,6 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_M32R_26_PCREL_RELA: case R_M32R_HI16_ULO_RELA: case R_M32R_LO16_RELA: - case R_M32R_SDA16_RELA: if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0 @@ -3094,6 +3163,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, goto check_reloc; + case (int) R_M32R_SDA16_RELA: case (int) R_M32R_SDA16 : { const char *name; @@ -3125,11 +3195,11 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, else { (*_bfd_error_handler) - (_("%s: The target (%s) of an %s relocation is in the wrong section (%s)"), - bfd_archive_filename (input_bfd), + (_("%B: The target (%s) of an %s relocation is in the wrong section (%A)"), + input_bfd, + sec, sym_name, - m32r_elf_howto_table[(int) r_type].name, - bfd_get_section_name (abfd, sec)); + m32r_elf_howto_table[(int) r_type].name); /*bfd_set_error (bfd_error_bad_value); ??? why? */ ret = FALSE; continue; @@ -3450,7 +3520,7 @@ printf("m32r_elf_finish_dynamic_sections()\n"); BFD_ASSERT (sgot != NULL && sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; - dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); + dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); for (; dyncon < dynconend; dyncon++) { @@ -3481,10 +3551,7 @@ printf("m32r_elf_finish_dynamic_sections()\n"); case DT_PLTRELSZ: s = htab->srelplt->output_section; BFD_ASSERT (s != NULL); - if (s->_cooked_size != 0) - dyn.d_un.d_val = s->_cooked_size; - else - dyn.d_un.d_val = s->_raw_size; + dyn.d_un.d_val = s->size; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; @@ -3501,10 +3568,7 @@ printf("m32r_elf_finish_dynamic_sections()\n"); if (htab->srelplt != NULL) { s = htab->srelplt->output_section; - if (s->_cooked_size != 0) - dyn.d_un.d_val -= s->_cooked_size; - else - dyn.d_un.d_val -= s->_raw_size; + dyn.d_un.d_val -= s->size; } bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; @@ -3513,7 +3577,7 @@ printf("m32r_elf_finish_dynamic_sections()\n"); /* Fill in the first entry in the procedure linkage table. */ splt = htab->splt; - if (splt && splt->_raw_size > 0) + if (splt && splt->size > 0) { if (info->shared) { @@ -3545,7 +3609,7 @@ printf("m32r_elf_finish_dynamic_sections()\n"); } /* Fill in the first three entries in the global offset table. */ - if (sgot && sgot->_raw_size > 0) + if (sgot && sgot->size > 0) { if (sdyn == NULL) bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); @@ -3615,11 +3679,6 @@ m32r_elf_relax_section (abfd, sec, link_info, again) || 0 /* FIXME: check SHF_M32R_CAN_RELAX */) return TRUE; - /* If this is the first time we have been called for this section, - initialize the cooked size. */ - if (sec->_cooked_size == 0) - sec->_cooked_size = sec->_raw_size; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Get a copy of the native relocations. */ @@ -3649,12 +3708,7 @@ m32r_elf_relax_section (abfd, sec, link_info, again) else { /* Go get them off disk. */ - contents = (bfd_byte *) bfd_malloc (sec->_raw_size); - if (contents == NULL) - goto error_return; - - if (! bfd_get_section_contents (abfd, sec, contents, - (file_ptr) 0, sec->_raw_size)) + if (!bfd_malloc_and_get_section (abfd, sec, &contents)) goto error_return; } } @@ -3734,7 +3788,7 @@ m32r_elf_relax_section (abfd, sec, link_info, again) /* Do nothing if no room in the section for this to be what we're looking for. */ - if (irel->r_offset > sec->_cooked_size - 8) + if (irel->r_offset > sec->size - 8) continue; /* Make sure the next relocation applies to the next @@ -3776,7 +3830,7 @@ m32r_elf_relax_section (abfd, sec, link_info, again) if (pcrel_value >= -(1 << 25) && pcrel_value < (1 << 25) + 4 /* Do nothing if no room in the section for this to be what we're looking for. */ - && (irel->r_offset <= sec->_cooked_size - 12) + && (irel->r_offset <= sec->size - 12) /* Ensure the next insn is "jl rN". */ && ((code = bfd_get_16 (abfd, contents + irel->r_offset + 8)), code != (0x1ec0 | reg))) @@ -3943,14 +3997,14 @@ m32r_elf_relax_delete_bytes (abfd, sec, addr, count) power larger than the number of bytes we are deleting. */ irelalign = NULL; - toaddr = sec->_cooked_size; + toaddr = sec->size; irel = elf_section_data (sec)->relocs; irelend = irel + sec->reloc_count; /* Actually delete the bytes. */ memmove (contents + addr, contents + addr + count, toaddr - addr - count); - sec->_cooked_size -= count; + sec->size -= count; /* Adjust all the relocs. */ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) @@ -4027,7 +4081,7 @@ m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; memcpy (data, elf_section_data (input_section)->this_hdr.contents, - input_section->_raw_size); + input_section->size); if ((input_section->flags & SEC_RELOC) != 0 && input_section->reloc_count > 0) @@ -4208,8 +4262,7 @@ m32r_elf_merge_private_bfd_data (ibfd, obfd) || ((in_flags & EF_M32R_ARCH) == E_M32R2_ARCH)) { (*_bfd_error_handler) - (_("%s: Instruction set mismatch with previous modules"), - bfd_archive_filename (ibfd)); + (_("%B: Instruction set mismatch with previous modules"), ibfd); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -4313,6 +4366,10 @@ m32r_elf_gc_sweep_hook (abfd, info, sec, relocs) case R_M32R_GOT16_HI_ULO: case R_M32R_GOT16_HI_SLO: case R_M32R_GOT16_LO: + case R_M32R_GOTOFF: + case R_M32R_GOTOFF_HI_ULO: + case R_M32R_GOTOFF_HI_SLO: + case R_M32R_GOTOFF_LO: case R_M32R_GOT24: case R_M32R_GOTPC_HI_ULO: case R_M32R_GOTPC_HI_SLO: @@ -4442,6 +4499,10 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) { case R_M32R_GOT16_HI_ULO: case R_M32R_GOT16_HI_SLO: + case R_M32R_GOTOFF: + case R_M32R_GOTOFF_HI_ULO: + case R_M32R_GOTOFF_HI_SLO: + case R_M32R_GOTOFF_LO: case R_M32R_GOT16_LO: case R_M32R_GOTPC24: case R_M32R_GOTPC_HI_ULO: |