X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-m32r.c;h=7ecf95fb03ebd20eab8da55e41b11e5e2e3eb57f;hb=63a5468afa8e2cf8843d87b99e780e9266b31014;hp=14aec619ef3cc39e34edb71cf1af957435df4e3c;hpb=eea6121ac0cb22524c627017191ca09825e3d702;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index 14aec619ef..7ecf95fb03 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -1,12 +1,11 @@ /* M32R-specific support for 32-bit ELF. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + Copyright (C) 1996-2017 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,97 +15,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/m32r.h" -static bfd_reloc_status_type m32r_elf_10_pcrel_reloc - PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -static bfd_reloc_status_type m32r_elf_do_10_pcrel_reloc - PARAMS ((bfd *, reloc_howto_type *, asection *, - bfd_byte *, bfd_vma, asection *, bfd_vma, bfd_vma)); -static bfd_reloc_status_type m32r_elf_hi16_reloc - PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -static void m32r_elf_relocate_hi16 - PARAMS ((bfd *, int, Elf_Internal_Rela *, Elf_Internal_Rela *, - bfd_byte *, bfd_vma)); -bfd_reloc_status_type m32r_elf_lo16_reloc - PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -bfd_reloc_status_type m32r_elf_generic_reloc - PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -static bfd_reloc_status_type m32r_elf_sda16_reloc - PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -static void m32r_info_to_howto_rel - PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); -static void m32r_info_to_howto - PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); -bfd_boolean _bfd_m32r_elf_section_from_bfd_section - PARAMS ((bfd *, asection *, int *)); -void _bfd_m32r_elf_symbol_processing - PARAMS ((bfd *, asymbol *)); -static bfd_boolean m32r_elf_add_symbol_hook - PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *, - const char **, flagword *, asection **, bfd_vma *)); -static bfd_boolean m32r_elf_relocate_section - PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, - Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -#if 0 /* not yet */ -static bfd_boolean m32r_elf_relax_delete_bytes - PARAMS ((bfd *, asection *, bfd_vma, int)); -#endif -static bfd_reloc_status_type m32r_elf_final_sda_base - PARAMS ((bfd *, struct bfd_link_info *, const char **, bfd_vma *)); -static bfd_boolean m32r_elf_object_p - PARAMS ((bfd *)); -static void m32r_elf_final_write_processing - PARAMS ((bfd *, bfd_boolean)); -static bfd_boolean m32r_elf_set_private_flags - PARAMS ((bfd *, flagword)); -static bfd_boolean m32r_elf_merge_private_bfd_data - PARAMS ((bfd *, bfd *)); -static bfd_boolean m32r_elf_print_private_bfd_data - PARAMS ((bfd *, PTR)); -static bfd_boolean m32r_elf_gc_sweep_hook - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); -static bfd_boolean m32r_elf_check_relocs - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); - -static bfd_boolean m32r_elf_adjust_dynamic_symbol - PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); -static bfd_boolean m32r_elf_size_dynamic_sections - PARAMS ((bfd *, struct bfd_link_info *)); - -asection * m32r_elf_gc_mark_hook - PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *, Elf_Internal_Sym *)); - -static bfd_boolean m32r_elf_create_dynamic_sections - PARAMS ((bfd *, struct bfd_link_info *)); - -static bfd_boolean m32r_elf_finish_dynamic_sections - PARAMS ((bfd *, struct bfd_link_info *)); - -static bfd_boolean m32r_elf_finish_dynamic_symbol - PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, - Elf_Internal_Sym *)); - -static bfd_boolean allocate_dynrelocs - PARAMS ((struct elf_link_hash_entry *, PTR)); -static bfd_boolean readonly_dynrelocs - PARAMS ((struct elf_link_hash_entry *, PTR)); -static enum elf_reloc_type_class m32r_elf_reloc_type_class - PARAMS ((const Elf_Internal_Rela *)); -static bfd_boolean m32r_elf_fake_sections - PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); - #define NOP_INSN 0x7000 #define MAKE_PARALLEL(insn) ((insn) | 0x8000) @@ -119,7 +36,7 @@ static bfd_boolean m32r_elf_fake_sections #ifndef USE_REL #define USE_REL 0 #endif */ -/* Use RELA. But use REL to link old objects for backwords compatibility. */ +/* Use RELA. But use REL to link old objects for backwords compatibility. */ /* Functions for the M32R ELF linker. */ @@ -164,1056 +81,1091 @@ static bfd_boolean m32r_elf_fake_sections #define PLT_ENTRY_WORD4 0xff000000 /* bra .plt0. */ -static reloc_howto_type m32r_elf_howto_table[] = -{ - /* This reloc does nothing. */ - HOWTO (R_M32R_NONE, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_NONE", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ +/* Utility to actually perform an R_M32R_10_PCREL reloc. */ - /* A 16 bit absolute relocation. */ - HOWTO (R_M32R_16, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - m32r_elf_generic_reloc,/* special_function */ - "R_M32R_16", /* name */ - TRUE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ +static bfd_reloc_status_type +m32r_elf_do_10_pcrel_reloc (bfd *abfd, + reloc_howto_type *howto, + asection *input_section, + bfd_byte *data, + bfd_vma offset, + asection *symbol_section ATTRIBUTE_UNUSED, + bfd_vma symbol_value, + bfd_vma addend) +{ + bfd_signed_vma relocation; + unsigned long x; + bfd_reloc_status_type status; - /* A 32 bit absolute relocation. */ - HOWTO (R_M32R_32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - m32r_elf_generic_reloc,/* special_function */ - "R_M32R_32", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + /* Sanity check the address (offset in section). */ + if (offset > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; - /* A 24 bit address. */ - HOWTO (R_M32R_24, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - m32r_elf_generic_reloc,/* special_function */ - "R_M32R_24", /* name */ - TRUE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + relocation = symbol_value + addend; + /* Make it pc relative. */ + relocation -= (input_section->output_section->vma + + input_section->output_offset); + /* These jumps mask off the lower two bits of the current address + before doing pcrel calculations. */ + relocation -= (offset & -(bfd_vma) 4); - /* An PC Relative 10-bit relocation, shifted by 2. - This reloc is complicated because relocations are relative to pc & -4. - i.e. branches in the right insn slot use the address of the left insn - slot for pc. */ - /* ??? It's not clear whether this should have partial_inplace set or not. - Branch relaxing in the assembler can store the addend in the insn, - and if bfd_install_relocation gets called the addend may get added - again. */ - HOWTO (R_M32R_10_PCREL, /* type */ - 2, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - m32r_elf_10_pcrel_reloc, /* special_function */ - "R_M32R_10_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - TRUE), /* pcrel_offset */ + if (relocation < -0x200 || relocation > 0x1ff) + status = bfd_reloc_overflow; + else + status = bfd_reloc_ok; - /* A relative 18 bit relocation, right shifted by 2. */ - HOWTO (R_M32R_18_PCREL, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_18_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + x = bfd_get_16 (abfd, data + offset); + relocation >>= howto->rightshift; + relocation <<= howto->bitpos; + x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask); + bfd_put_16 (abfd, (bfd_vma) x, data + offset); - /* A relative 26 bit relocation, right shifted by 2. */ - /* ??? It's not clear whether this should have partial_inplace set or not. - Branch relaxing in the assembler can store the addend in the insn, - and if bfd_install_relocation gets called the addend may get added - again. */ - HOWTO (R_M32R_26_PCREL, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 26, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_26_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + return status; +} - /* High 16 bits of address when lower 16 is or'd in. */ - HOWTO (R_M32R_HI16_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 */ - m32r_elf_hi16_reloc, /* special_function */ - "R_M32R_HI16_ULO", /* name */ - TRUE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ +/* Handle the R_M32R_10_PCREL reloc. */ - /* High 16 bits of address when lower 16 is added in. */ - HOWTO (R_M32R_HI16_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 */ - m32r_elf_hi16_reloc, /* special_function */ - "R_M32R_HI16_SLO", /* name */ - TRUE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ +static bfd_reloc_status_type +m32r_elf_10_pcrel_reloc (bfd * abfd, + arelent * reloc_entry, + asymbol * symbol, + void * data, + asection * input_section, + bfd * output_bfd, + char ** error_message ATTRIBUTE_UNUSED) +{ + /* This part is from bfd_elf_generic_reloc. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (! reloc_entry->howto->partial_inplace + || reloc_entry->addend == 0)) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } - /* Lower 16 bits of address. */ - HOWTO (R_M32R_LO16, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - m32r_elf_lo16_reloc, /* special_function */ - "R_M32R_LO16", /* name */ - TRUE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + if (output_bfd != NULL) + /* FIXME: See bfd_perform_relocation. Is this right? */ + return bfd_reloc_continue; - /* Small data area 16 bits offset. */ - HOWTO (R_M32R_SDA16, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - m32r_elf_sda16_reloc, /* special_function */ - "R_M32R_SDA16", /* name */ - TRUE, /* partial_inplace */ /* FIXME: correct? */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + return m32r_elf_do_10_pcrel_reloc (abfd, reloc_entry->howto, + input_section, + data, reloc_entry->address, + symbol->section, + (symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset), + reloc_entry->addend); +} - /* GNU extension to record C++ vtable hierarchy */ - HOWTO (R_M32R_GNU_VTINHERIT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - NULL, /* special_function */ - "R_M32R_GNU_VTINHERIT", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ +/* Do generic partial_inplace relocation. + This is a local replacement for bfd_elf_generic_reloc. */ - /* GNU extension to record C++ vtable member usage */ - HOWTO (R_M32R_GNU_VTENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - _bfd_elf_rel_vtable_reloc_fn, /* special_function */ - "R_M32R_GNU_VTENTRY", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ +static bfd_reloc_status_type +m32r_elf_generic_reloc (bfd *input_bfd, + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_reloc_status_type ret; + bfd_vma relocation; + bfd_byte *inplace_address; - EMPTY_HOWTO (13), - EMPTY_HOWTO (14), - EMPTY_HOWTO (15), - EMPTY_HOWTO (16), - EMPTY_HOWTO (17), - EMPTY_HOWTO (18), - EMPTY_HOWTO (19), - EMPTY_HOWTO (20), - EMPTY_HOWTO (21), - EMPTY_HOWTO (22), - EMPTY_HOWTO (23), - EMPTY_HOWTO (24), - EMPTY_HOWTO (25), - EMPTY_HOWTO (26), - EMPTY_HOWTO (27), - EMPTY_HOWTO (28), - EMPTY_HOWTO (29), - EMPTY_HOWTO (30), - EMPTY_HOWTO (31), - EMPTY_HOWTO (32), + /* This part is from bfd_elf_generic_reloc. + If we're relocating, and this an external symbol, we don't want + to change anything. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && reloc_entry->addend == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } - /* A 16 bit absolute relocation. */ - HOWTO (R_M32R_16_RELA, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_16_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + /* Now do the reloc in the usual way. + ??? It would be nice to call bfd_elf_generic_reloc here, + but we have partial_inplace set. bfd_elf_generic_reloc will + pass the handling back to bfd_install_relocation which will install + a section relative addend which is wrong. */ - /* A 32 bit absolute relocation. */ - HOWTO (R_M32R_32_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc,/* special_function */ - "R_M32R_32_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + /* Sanity check the address (offset in section). */ + if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section)) + return bfd_reloc_outofrange; - /* A 24 bit address. */ - HOWTO (R_M32R_24_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc,/* special_function */ - "R_M32R_24_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + ret = bfd_reloc_ok; + if (bfd_is_und_section (symbol->section) + && output_bfd == NULL) + ret = bfd_reloc_undefined; - HOWTO (R_M32R_10_PCREL_RELA, /* type */ - 2, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - m32r_elf_10_pcrel_reloc, /* special_function */ - "R_M32R_10_PCREL_RELA",/* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - TRUE), /* pcrel_offset */ + if (bfd_is_com_section (symbol->section) + || output_bfd != NULL) + relocation = 0; + else + relocation = symbol->value; - /* A relative 18 bit relocation, right shifted by 2. */ - HOWTO (R_M32R_18_PCREL_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_18_PCREL_RELA",/* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + /* Only do this for a final link. */ + if (output_bfd == NULL) + { + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + } - /* A relative 26 bit relocation, right shifted by 2. */ - HOWTO (R_M32R_26_PCREL_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 26, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_26_PCREL_RELA",/* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + relocation += reloc_entry->addend; + inplace_address = (bfd_byte *) data + reloc_entry->address; - /* High 16 bits of address when lower 16 is or'd in. */ - HOWTO (R_M32R_HI16_ULO_RELA, /* 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_HI16_ULO_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ +#define DOIT(x) \ + x = ( (x & ~reloc_entry->howto->dst_mask) | \ + (((x & reloc_entry->howto->src_mask) + relocation) & \ + reloc_entry->howto->dst_mask)) - /* High 16 bits of address when lower 16 is added in. */ - HOWTO (R_M32R_HI16_SLO_RELA, /* 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_HI16_SLO_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + switch (reloc_entry->howto->size) + { + case 1: + { + short x = bfd_get_16 (input_bfd, inplace_address); + DOIT (x); + bfd_put_16 (input_bfd, (bfd_vma) x, inplace_address); + } + break; + case 2: + { + unsigned long x = bfd_get_32 (input_bfd, inplace_address); + DOIT (x); + bfd_put_32 (input_bfd, (bfd_vma)x , inplace_address); + } + break; + default: + BFD_ASSERT (0); + } - /* Lower 16 bits of address. */ - HOWTO (R_M32R_LO16_RELA, /* 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_LO16_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + if (output_bfd != NULL) + reloc_entry->address += input_section->output_offset; - /* Small data area 16 bits offset. */ - HOWTO (R_M32R_SDA16_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_SDA16_RELA", /* name */ - TRUE, /* partial_inplace */ /* FIXME: correct? */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + return ret; +} - /* GNU extension to record C++ vtable hierarchy */ - HOWTO (R_M32R_RELA_GNU_VTINHERIT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - NULL, /* special_function */ - "R_M32R_RELA_GNU_VTINHERIT", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ +/* Handle the R_M32R_SDA16 reloc. + This reloc is used to compute the address of objects in the small data area + and to perform loads and stores from that area. + The lower 16 bits are sign extended and added to the register specified + in the instruction, which is assumed to point to _SDA_BASE_. */ - /* GNU extension to record C++ vtable member usage */ - HOWTO (R_M32R_RELA_GNU_VTENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - _bfd_elf_rel_vtable_reloc_fn, /* special_function */ - "R_M32R_RELA_GNU_VTENTRY", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ +static bfd_reloc_status_type +m32r_elf_sda16_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol, + void * data ATTRIBUTE_UNUSED, + asection *input_section, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + /* This part is from bfd_elf_generic_reloc. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (! reloc_entry->howto->partial_inplace + || reloc_entry->addend == 0)) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } - EMPTY_HOWTO (45), - EMPTY_HOWTO (46), - EMPTY_HOWTO (47), + if (output_bfd != NULL) + /* FIXME: See bfd_perform_relocation. Is this right? */ + return bfd_reloc_continue; - /* Like R_M32R_24, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOT24, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GOT24", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + /* FIXME: not sure what to do here yet. But then again, the linker + may never call us. */ + abort (); +} - /* Like R_M32R_PCREL, but referring to the procedure linkage table - entry for the symbol. */ - HOWTO (R_M32R_26_PLTREL, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_26_PLTREL", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + +/* Handle the R_M32R_HI16_[SU]LO relocs. + HI16_SLO is for the add3 and load/store with displacement instructions. + HI16_ULO is for the or3 instruction. + For R_M32R_HI16_SLO, the lower 16 bits are sign extended when added to + the high 16 bytes so if the lower 16 bits are negative (bit 15 == 1) then + we must add one to the high 16 bytes (which will get subtracted off when + the low 16 bits are added). + These relocs have to be done in combination with an R_M32R_LO16 reloc + because there is a carry from the LO16 to the HI16. Here we just save + the information we need; we do the actual relocation when we see the LO16. + This code is copied from the elf32-mips.c. We also support an arbitrary + number of HI16 relocs to be associated with a single LO16 reloc. The + assembler sorts the relocs to ensure each HI16 immediately precedes its + LO16. However if there are multiple copies, the assembler may not find + the real LO16 so it picks the first one it finds. */ - /* This is used only by the dynamic linker. The symbol should exist - both in the object being run and in some shared library. The - dynamic linker copies the data addressed by the symbol from the - shared library into the object, because the object being - run has to have the data at some particular address. */ - HOWTO (R_M32R_COPY, /* type */ +struct m32r_hi16 +{ + struct m32r_hi16 *next; + bfd_byte *addr; + bfd_vma addend; +}; + +/* FIXME: This should not be a static variable. */ + +static struct m32r_hi16 *m32r_hi16_list; + +static bfd_reloc_status_type +m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_reloc_status_type ret; + bfd_vma relocation; + struct m32r_hi16 *n; + + /* This part is from bfd_elf_generic_reloc. + If we're relocating, and this an external symbol, we don't want + to change anything. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && reloc_entry->addend == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + /* Sanity check the address (offset in section). */ + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + ret = bfd_reloc_ok; + if (bfd_is_und_section (symbol->section) + && output_bfd == NULL) + ret = bfd_reloc_undefined; + + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + relocation += reloc_entry->addend; + + /* Save the information, and let LO16 do the actual relocation. */ + n = bfd_malloc ((bfd_size_type) sizeof *n); + if (n == NULL) + return bfd_reloc_outofrange; + n->addr = (bfd_byte *) data + reloc_entry->address; + n->addend = relocation; + n->next = m32r_hi16_list; + m32r_hi16_list = n; + + if (output_bfd != NULL) + reloc_entry->address += input_section->output_offset; + + return ret; +} + +/* Handle an M32R ELF HI16 reloc. */ + +static void +m32r_elf_relocate_hi16 (bfd *input_bfd, + int type, + Elf_Internal_Rela *relhi, + Elf_Internal_Rela *rello, + bfd_byte *contents, + bfd_vma addend) +{ + unsigned long insn; + bfd_vma addlo; + + insn = bfd_get_32 (input_bfd, contents + relhi->r_offset); + + addlo = bfd_get_32 (input_bfd, contents + rello->r_offset); + if (type == R_M32R_HI16_SLO) + addlo = ((addlo & 0xffff) ^ 0x8000) - 0x8000; + else + addlo &= 0xffff; + + addend += ((insn & 0xffff) << 16) + addlo; + + /* Reaccount for sign extension of low part. */ + if (type == R_M32R_HI16_SLO + && (addend & 0x8000) != 0) + addend += 0x10000; + + bfd_put_32 (input_bfd, + (insn & 0xffff0000) | ((addend >> 16) & 0xffff), + contents + relhi->r_offset); +} + +/* Do an R_M32R_LO16 relocation. This is a straightforward 16 bit + inplace relocation; this function exists in order to do the + R_M32R_HI16_[SU]LO relocation described above. */ + +static bfd_reloc_status_type +m32r_elf_lo16_reloc (bfd *input_bfd, + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message) +{ + /* This part is from bfd_elf_generic_reloc. + If we're relocating, and this an external symbol, we don't want + to change anything. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && reloc_entry->addend == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + if (m32r_hi16_list != NULL) + { + struct m32r_hi16 *l; + + l = m32r_hi16_list; + while (l != NULL) + { + unsigned long insn; + unsigned long val; + unsigned long vallo; + struct m32r_hi16 *next; + + /* Do the HI16 relocation. Note that we actually don't need + to know anything about the LO16 itself, except where to + find the low 16 bits of the addend needed by the LO16. */ + insn = bfd_get_32 (input_bfd, l->addr); + vallo = ((bfd_get_32 (input_bfd, (bfd_byte *) data + reloc_entry->address) + & 0xffff) ^ 0x8000) - 0x8000; + val = ((insn & 0xffff) << 16) + vallo; + val += l->addend; + + /* Reaccount for sign extension of low part. */ + if ((val & 0x8000) != 0) + val += 0x10000; + + insn = (insn &~ (bfd_vma) 0xffff) | ((val >> 16) & 0xffff); + bfd_put_32 (input_bfd, (bfd_vma) insn, l->addr); + + next = l->next; + free (l); + l = next; + } + + m32r_hi16_list = NULL; + } + + /* Now do the LO16 reloc in the usual way. + ??? It would be nice to call bfd_elf_generic_reloc here, + but we have partial_inplace set. bfd_elf_generic_reloc will + pass the handling back to bfd_install_relocation which will install + a section relative addend which is wrong. */ + return m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); +} + + +static reloc_howto_type m32r_elf_howto_table[] = +{ + /* This reloc does nothing. */ + HOWTO (R_M32R_NONE, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_COPY", /* name */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_NONE", /* name */ FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + 0, /* src_mask */ + 0, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Like R_M32R_24, but used when setting global offset table - entries. */ - HOWTO (R_M32R_GLOB_DAT, /* type */ + /* A 16 bit absolute relocation. */ + HOWTO (R_M32R_16, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GLOB_DAT", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + m32r_elf_generic_reloc,/* special_function */ + "R_M32R_16", /* name */ + TRUE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Marks a procedure linkage table entry for a symbol. */ - HOWTO (R_M32R_JMP_SLOT, /* type */ + /* A 32 bit absolute relocation. */ + HOWTO (R_M32R_32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_JMP_SLOT", /* name */ - FALSE, /* partial_inplace */ + m32r_elf_generic_reloc,/* special_function */ + "R_M32R_32", /* name */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Used only by the dynamic linker. When the object is run, this - longword is set to the load address of the object, plus the - addend. */ - HOWTO (R_M32R_RELATIVE, /* type */ + /* A 24 bit address. */ + HOWTO (R_M32R_24, /* 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_RELATIVE", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + complain_overflow_unsigned, /* complain_on_overflow */ + m32r_elf_generic_reloc,/* special_function */ + "R_M32R_24", /* name */ + TRUE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (R_M32R_GOTOFF, /* type */ - 0, /* rightshift */ + /* An PC Relative 10-bit relocation, shifted by 2. + This reloc is complicated because relocations are relative to pc & -4. + i.e. branches in the right insn slot use the address of the left insn + slot for pc. */ + /* ??? It's not clear whether this should have partial_inplace set or not. + Branch relaxing in the assembler can store the addend in the insn, + and if bfd_install_relocation gets called the addend may get added + again. */ + HOWTO (R_M32R_10_PCREL, /* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + m32r_elf_10_pcrel_reloc, /* special_function */ + "R_M32R_10_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A relative 18 bit relocation, right shifted by 2. */ + HOWTO (R_M32R_18_PCREL, /* type */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ + 16, /* bitsize */ + TRUE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GOTOFF", /* name */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_18_PCREL", /* name */ FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - /* An PC Relative 24-bit relocation used when setting PIC offset - table register. */ - HOWTO (R_M32R_GOTPC24, /* type */ - 0, /* rightshift */ + /* A relative 26 bit relocation, right shifted by 2. */ + /* ??? It's not clear whether this should have partial_inplace set or not. + Branch relaxing in the assembler can store the addend in the insn, + and if bfd_install_relocation gets called the addend may get added + again. */ + HOWTO (R_M32R_26_PCREL, /* type */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ + 26, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GOTPC24", /* name */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_26_PCREL", /* name */ FALSE, /* partial_inplace */ 0xffffff, /* src_mask */ 0xffffff, /* dst_mask */ TRUE), /* pcrel_offset */ - /* Like R_M32R_HI16_ULO, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOT16_HI_ULO, /* type */ + /* High 16 bits of address when lower 16 is or'd in. */ + HOWTO (R_M32R_HI16_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_GOT16_HI_ULO", /* name */ - FALSE, /* partial_inplace */ + m32r_elf_hi16_reloc, /* special_function */ + "R_M32R_HI16_ULO", /* name */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Like R_M32R_HI16_SLO, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOT16_HI_SLO, /* type */ + /* High 16 bits of address when lower 16 is added in. */ + HOWTO (R_M32R_HI16_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_GOT16_HI_SLO", /* name */ - FALSE, /* partial_inplace */ + m32r_elf_hi16_reloc, /* special_function */ + "R_M32R_HI16_SLO", /* name */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Like R_M32R_LO16, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOT16_LO, /* type */ + /* Lower 16 bits of address. */ + HOWTO (R_M32R_LO16, /* 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_GOT16_LO", /* name */ - FALSE, /* partial_inplace */ + m32r_elf_lo16_reloc, /* special_function */ + "R_M32R_LO16", /* name */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* An PC Relative relocation used when setting PIC offset table register. - Like R_M32R_HI16_ULO, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOTPC_HI_ULO, /* type */ - 16, /* rightshift */ + /* Small data area 16 bits offset. */ + HOWTO (R_M32R_SDA16, /* 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_GOTPC_HI_ULO", /* name */ - FALSE, /* partial_inplace */ + complain_overflow_signed, /* complain_on_overflow */ + m32r_elf_sda16_reloc, /* special_function */ + "R_M32R_SDA16", /* name */ + TRUE, /* partial_inplace */ /* FIXME: correct? */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ - /* An PC Relative relocation used when setting PIC offset table register. - Like R_M32R_HI16_SLO, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOTPC_HI_SLO, /* type */ - 16, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + /* GNU extension to record C++ vtable hierarchy. */ + HOWTO (R_M32R_GNU_VTINHERIT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + NULL, /* special_function */ + "R_M32R_GNU_VTINHERIT", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GNU extension to record C++ vtable member usage. */ + HOWTO (R_M32R_GNU_VTENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn, /* special_function */ + "R_M32R_GNU_VTENTRY", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (13), + EMPTY_HOWTO (14), + EMPTY_HOWTO (15), + EMPTY_HOWTO (16), + EMPTY_HOWTO (17), + EMPTY_HOWTO (18), + EMPTY_HOWTO (19), + EMPTY_HOWTO (20), + EMPTY_HOWTO (21), + EMPTY_HOWTO (22), + EMPTY_HOWTO (23), + EMPTY_HOWTO (24), + EMPTY_HOWTO (25), + EMPTY_HOWTO (26), + EMPTY_HOWTO (27), + EMPTY_HOWTO (28), + EMPTY_HOWTO (29), + EMPTY_HOWTO (30), + EMPTY_HOWTO (31), + EMPTY_HOWTO (32), + + /* A 16 bit absolute relocation. */ + HOWTO (R_M32R_16_RELA, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GOTPC_HI_SLO", /* name */ + "R_M32R_16_RELA", /* name */ FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - /* An PC Relative relocation used when setting PIC offset table register. - Like R_M32R_LO16, but referring to the GOT table entry for - the symbol. */ - HOWTO (R_M32R_GOTPC_LO, /* type */ + /* A 32 bit absolute relocation. */ + HOWTO (R_M32R_32_RELA, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ + 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_M32R_GOTPC_LO", /* name */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc,/* special_function */ + "R_M32R_32_RELA", /* name */ FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - TRUE), /* pcrel_offset */ -}; - -/* Handle the R_M32R_10_PCREL reloc. */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ -static bfd_reloc_status_type -m32r_elf_10_pcrel_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message) - bfd * abfd; - arelent * reloc_entry; - asymbol * symbol; - PTR data; - asection * input_section; - bfd * output_bfd; - char ** error_message ATTRIBUTE_UNUSED; -{ - /* This part is from bfd_elf_generic_reloc. */ - if (output_bfd != (bfd *) NULL - && (symbol->flags & BSF_SECTION_SYM) == 0 - && (! reloc_entry->howto->partial_inplace - || reloc_entry->addend == 0)) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } + /* A 24 bit address. */ + HOWTO (R_M32R_24_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc,/* special_function */ + "R_M32R_24_RELA", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - if (output_bfd != NULL) - { - /* FIXME: See bfd_perform_relocation. Is this right? */ - return bfd_reloc_continue; - } + HOWTO (R_M32R_10_PCREL_RELA, /* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + m32r_elf_10_pcrel_reloc, /* special_function */ + "R_M32R_10_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ - return m32r_elf_do_10_pcrel_reloc (abfd, reloc_entry->howto, - input_section, - data, reloc_entry->address, - symbol->section, - (symbol->value - + symbol->section->output_section->vma - + symbol->section->output_offset), - reloc_entry->addend); -} - -/* Utility to actually perform an R_M32R_10_PCREL reloc. */ + /* A relative 18 bit relocation, right shifted by 2. */ + HOWTO (R_M32R_18_PCREL_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_18_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ -static bfd_reloc_status_type -m32r_elf_do_10_pcrel_reloc (abfd, howto, input_section, data, offset, - symbol_section, symbol_value, addend) - bfd *abfd; - reloc_howto_type *howto; - asection *input_section; - bfd_byte *data; - bfd_vma offset; - asection *symbol_section ATTRIBUTE_UNUSED; - bfd_vma symbol_value; - bfd_vma addend; -{ - bfd_signed_vma relocation; - bfd_size_type sz; - unsigned long x; - bfd_reloc_status_type status; + /* A relative 26 bit relocation, right shifted by 2. */ + HOWTO (R_M32R_26_PCREL_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 26, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_26_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - /* Sanity check the address (offset in section). */ - sz = input_section->rawsize ? input_section->rawsize : input_section->size; - if (offset > sz) - return bfd_reloc_outofrange; + /* High 16 bits of address when lower 16 is or'd in. */ + HOWTO (R_M32R_HI16_ULO_RELA, /* 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_HI16_ULO_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - relocation = symbol_value + addend; - /* Make it pc relative. */ - relocation -= (input_section->output_section->vma - + input_section->output_offset); - /* These jumps mask off the lower two bits of the current address - before doing pcrel calculations. */ - relocation -= (offset & -(bfd_vma) 4); + /* High 16 bits of address when lower 16 is added in. */ + HOWTO (R_M32R_HI16_SLO_RELA, /* 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_HI16_SLO_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - if (relocation < -0x200 || relocation > 0x1ff) - status = bfd_reloc_overflow; - else - status = bfd_reloc_ok; + /* Lower 16 bits of address. */ + HOWTO (R_M32R_LO16_RELA, /* 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_LO16_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - x = bfd_get_16 (abfd, data + offset); - relocation >>= howto->rightshift; - relocation <<= howto->bitpos; - x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask); - bfd_put_16 (abfd, (bfd_vma) x, data + offset); + /* Small data area 16 bits offset. */ + HOWTO (R_M32R_SDA16_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_SDA16_RELA", /* name */ + TRUE, /* partial_inplace */ /* FIXME: correct? */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - return status; -} + /* GNU extension to record C++ vtable hierarchy. */ + HOWTO (R_M32R_RELA_GNU_VTINHERIT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + NULL, /* special_function */ + "R_M32R_RELA_GNU_VTINHERIT", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ -/* Handle the R_M32R_HI16_[SU]LO relocs. - HI16_SLO is for the add3 and load/store with displacement instructions. - HI16_ULO is for the or3 instruction. - For R_M32R_HI16_SLO, the lower 16 bits are sign extended when added to - the high 16 bytes so if the lower 16 bits are negative (bit 15 == 1) then - we must add one to the high 16 bytes (which will get subtracted off when - the low 16 bits are added). - These relocs have to be done in combination with an R_M32R_LO16 reloc - because there is a carry from the LO16 to the HI16. Here we just save - the information we need; we do the actual relocation when we see the LO16. - This code is copied from the elf32-mips.c. We also support an arbitrary - number of HI16 relocs to be associated with a single LO16 reloc. The - assembler sorts the relocs to ensure each HI16 immediately precedes its - LO16. However if there are multiple copies, the assembler may not find - the real LO16 so it picks the first one it finds. */ + /* GNU extension to record C++ vtable member usage. */ + HOWTO (R_M32R_RELA_GNU_VTENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn, /* special_function */ + "R_M32R_RELA_GNU_VTENTRY", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ -struct m32r_hi16 -{ - struct m32r_hi16 *next; - bfd_byte *addr; - bfd_vma addend; -}; + /* A 32 bit PC relative relocation. */ + HOWTO (R_M32R_REL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc,/* special_function */ + "R_M32R_REL32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ -/* FIXME: This should not be a static variable. */ + EMPTY_HOWTO (46), + EMPTY_HOWTO (47), -static struct m32r_hi16 *m32r_hi16_list; + /* Like R_M32R_24, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOT24, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_GOT24", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ -static bfd_reloc_status_type -m32r_elf_hi16_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *reloc_entry; - asymbol *symbol; - PTR data; - asection *input_section; - bfd *output_bfd; - char **error_message ATTRIBUTE_UNUSED; -{ - bfd_reloc_status_type ret; - bfd_vma relocation; - bfd_size_type sz; - struct m32r_hi16 *n; + /* Like R_M32R_PCREL, but referring to the procedure linkage table + entry for the symbol. */ + HOWTO (R_M32R_26_PLTREL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_26_PLTREL", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - /* This part is from bfd_elf_generic_reloc. - If we're relocating, and this an external symbol, we don't want - to change anything. */ - if (output_bfd != (bfd *) NULL - && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } + /* This is used only by the dynamic linker. The symbol should exist + both in the object being run and in some shared library. The + dynamic linker copies the data addressed by the symbol from the + shared library into the object, because the object being + run has to have the data at some particular address. */ + HOWTO (R_M32R_COPY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_COPY", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - /* Sanity check the address (offset in section). */ - sz = input_section->rawsize ? input_section->rawsize : input_section->size; - if (reloc_entry->address > sz) - return bfd_reloc_outofrange; + /* Like R_M32R_24, but used when setting global offset table + entries. */ + HOWTO (R_M32R_GLOB_DAT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_GLOB_DAT", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - ret = bfd_reloc_ok; - if (bfd_is_und_section (symbol->section) - && output_bfd == (bfd *) NULL) - ret = bfd_reloc_undefined; - - if (bfd_is_com_section (symbol->section)) - relocation = 0; - else - relocation = symbol->value; - - relocation += symbol->section->output_section->vma; - relocation += symbol->section->output_offset; - relocation += reloc_entry->addend; - - /* Save the information, and let LO16 do the actual relocation. */ - n = (struct m32r_hi16 *) bfd_malloc ((bfd_size_type) sizeof *n); - if (n == NULL) - return bfd_reloc_outofrange; - n->addr = (bfd_byte *) data + reloc_entry->address; - n->addend = relocation; - n->next = m32r_hi16_list; - m32r_hi16_list = n; - - if (output_bfd != (bfd *) NULL) - reloc_entry->address += input_section->output_offset; - - return ret; -} - -/* Handle an M32R ELF HI16 reloc. */ - -static void -m32r_elf_relocate_hi16 (input_bfd, type, relhi, rello, contents, addend) - bfd *input_bfd; - int type; - Elf_Internal_Rela *relhi; - Elf_Internal_Rela *rello; - bfd_byte *contents; - bfd_vma addend; -{ - unsigned long insn; - bfd_vma addlo; - - insn = bfd_get_32 (input_bfd, contents + relhi->r_offset); - - addlo = bfd_get_32 (input_bfd, contents + rello->r_offset); - if (type == R_M32R_HI16_SLO) - addlo = ((addlo & 0xffff) ^ 0x8000) - 0x8000; - else - addlo &= 0xffff; - - addend += ((insn & 0xffff) << 16) + addlo; - - /* Reaccount for sign extension of low part. */ - if (type == R_M32R_HI16_SLO - && (addend & 0x8000) != 0) - addend += 0x10000; - - bfd_put_32 (input_bfd, - (insn & 0xffff0000) | ((addend >> 16) & 0xffff), - contents + relhi->r_offset); -} - -/* Do an R_M32R_LO16 relocation. This is a straightforward 16 bit - inplace relocation; this function exists in order to do the - R_M32R_HI16_[SU]LO relocation described above. */ - -bfd_reloc_status_type -m32r_elf_lo16_reloc (input_bfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message) - bfd *input_bfd; - arelent *reloc_entry; - asymbol *symbol; - PTR data; - asection *input_section; - bfd *output_bfd; - char **error_message; -{ - /* This part is from bfd_elf_generic_reloc. - If we're relocating, and this an external symbol, we don't want - to change anything. */ - if (output_bfd != (bfd *) NULL - && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } - - if (m32r_hi16_list != NULL) - { - struct m32r_hi16 *l; - - l = m32r_hi16_list; - while (l != NULL) - { - unsigned long insn; - unsigned long val; - unsigned long vallo; - struct m32r_hi16 *next; - - /* Do the HI16 relocation. Note that we actually don't need - to know anything about the LO16 itself, except where to - find the low 16 bits of the addend needed by the LO16. */ - insn = bfd_get_32 (input_bfd, l->addr); - vallo = ((bfd_get_32 (input_bfd, (bfd_byte *) data + reloc_entry->address) - & 0xffff) ^ 0x8000) - 0x8000; - val = ((insn & 0xffff) << 16) + vallo; - val += l->addend; - - /* Reaccount for sign extension of low part. */ - if ((val & 0x8000) != 0) - val += 0x10000; - - insn = (insn &~ (bfd_vma) 0xffff) | ((val >> 16) & 0xffff); - bfd_put_32 (input_bfd, (bfd_vma) insn, l->addr); - - next = l->next; - free (l); - l = next; - } - - m32r_hi16_list = NULL; - } - - /* Now do the LO16 reloc in the usual way. - ??? It would be nice to call bfd_elf_generic_reloc here, - but we have partial_inplace set. bfd_elf_generic_reloc will - pass the handling back to bfd_install_relocation which will install - a section relative addend which is wrong. */ - return m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message); -} - -/* Do generic partial_inplace relocation. - This is a local replacement for bfd_elf_generic_reloc. */ - -bfd_reloc_status_type -m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message) - bfd *input_bfd; - arelent *reloc_entry; - asymbol *symbol; - PTR data; - asection *input_section; - bfd *output_bfd; - char **error_message ATTRIBUTE_UNUSED; -{ - bfd_reloc_status_type ret; - bfd_vma relocation; - bfd_size_type sz; - bfd_byte *inplace_address; - - /* This part is from bfd_elf_generic_reloc. - If we're relocating, and this an external symbol, we don't want - to change anything. */ - if (output_bfd != (bfd *) NULL - && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } - - /* Now do the reloc in the usual way. - ??? It would be nice to call bfd_elf_generic_reloc here, - but we have partial_inplace set. bfd_elf_generic_reloc will - pass the handling back to bfd_install_relocation which will install - a section relative addend which is wrong. */ + /* Marks a procedure linkage table entry for a symbol. */ + HOWTO (R_M32R_JMP_SLOT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_JMP_SLOT", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - /* Sanity check the address (offset in section). */ - sz = input_section->rawsize ? input_section->rawsize : input_section->size; - if (reloc_entry->address > sz) - return bfd_reloc_outofrange; + /* Used only by the dynamic linker. When the object is run, this + longword is set to the load address of the object, plus the + addend. */ + HOWTO (R_M32R_RELATIVE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_RELATIVE", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - ret = bfd_reloc_ok; - if (bfd_is_und_section (symbol->section) - && output_bfd == (bfd *) NULL) - ret = bfd_reloc_undefined; + HOWTO (R_M32R_GOTOFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_GOTOFF", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - if (bfd_is_com_section (symbol->section) - || output_bfd != (bfd *) NULL) - relocation = 0; - else - relocation = symbol->value; + /* An PC Relative 24-bit relocation used when setting PIC offset + table register. */ + HOWTO (R_M32R_GOTPC24, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_M32R_GOTPC24", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - /* Only do this for a final link. */ - if (output_bfd == (bfd *) NULL) - { - relocation += symbol->section->output_section->vma; - relocation += symbol->section->output_offset; - } + /* Like R_M32R_HI16_ULO, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOT16_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_GOT16_HI_ULO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - relocation += reloc_entry->addend; - inplace_address = (bfd_byte *) data + reloc_entry->address; + /* Like R_M32R_HI16_SLO, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOT16_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_GOT16_HI_SLO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ -#define DOIT(x) \ - x = ( (x & ~reloc_entry->howto->dst_mask) | \ - (((x & reloc_entry->howto->src_mask) + relocation) & \ - reloc_entry->howto->dst_mask)) + /* Like R_M32R_LO16, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOT16_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_GOT16_LO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - switch (reloc_entry->howto->size) - { - case 1: - { - short x = bfd_get_16 (input_bfd, inplace_address); - DOIT (x); - bfd_put_16 (input_bfd, (bfd_vma) x, inplace_address); - } - break; - case 2: - { - unsigned long x = bfd_get_32 (input_bfd, inplace_address); - DOIT (x); - bfd_put_32 (input_bfd, (bfd_vma)x , inplace_address); - } - break; - default: - BFD_ASSERT (0); - } + /* An PC Relative relocation used when setting PIC offset table register. + Like R_M32R_HI16_ULO, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOTPC_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_GOTPC_HI_ULO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - if (output_bfd != (bfd *) NULL) - reloc_entry->address += input_section->output_offset; + /* An PC Relative relocation used when setting PIC offset table register. + Like R_M32R_HI16_SLO, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOTPC_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_GOTPC_HI_SLO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - return ret; -} + /* An PC Relative relocation used when setting PIC offset table register. + Like R_M32R_LO16, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_M32R_GOTPC_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_GOTPC_LO", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ -/* Handle the R_M32R_SDA16 reloc. - This reloc is used to compute the address of objects in the small data area - and to perform loads and stores from that area. - The lower 16 bits are sign extended and added to the register specified - in the instruction, which is assumed to point to _SDA_BASE_. */ + 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 */ -static bfd_reloc_status_type -m32r_elf_sda16_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *reloc_entry; - asymbol *symbol; - PTR data ATTRIBUTE_UNUSED; - asection *input_section; - bfd *output_bfd; - char **error_message ATTRIBUTE_UNUSED; -{ - /* This part is from bfd_elf_generic_reloc. */ - if (output_bfd != (bfd *) NULL - && (symbol->flags & BSF_SECTION_SYM) == 0 - && (! reloc_entry->howto->partial_inplace - || reloc_entry->addend == 0)) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } + 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 */ - if (output_bfd != NULL) - { - /* FIXME: See bfd_perform_relocation. Is this right? */ - return bfd_reloc_continue; - } + 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 */ +}; - /* FIXME: not sure what to do here yet. But then again, the linker - may never call us. */ - abort (); -} - /* Map BFD reloc types to M32R ELF reloc types. */ struct m32r_reloc_map @@ -1222,6 +1174,7 @@ struct m32r_reloc_map unsigned char elf_reloc_val; }; +#ifdef USE_M32R_OLD_RELOC static const struct m32r_reloc_map m32r_reloc_map_old[] = { { BFD_RELOC_NONE, R_M32R_NONE }, @@ -1238,7 +1191,7 @@ static const struct m32r_reloc_map m32r_reloc_map_old[] = { BFD_RELOC_VTABLE_INHERIT, R_M32R_GNU_VTINHERIT }, { BFD_RELOC_VTABLE_ENTRY, R_M32R_GNU_VTENTRY }, }; - +#else static const struct m32r_reloc_map m32r_reloc_map[] = { { BFD_RELOC_NONE, R_M32R_NONE }, @@ -1254,6 +1207,7 @@ static const struct m32r_reloc_map m32r_reloc_map[] = { BFD_RELOC_M32R_SDA16, R_M32R_SDA16_RELA }, { BFD_RELOC_VTABLE_INHERIT, R_M32R_RELA_GNU_VTINHERIT }, { BFD_RELOC_VTABLE_ENTRY, R_M32R_RELA_GNU_VTENTRY }, + { BFD_RELOC_32_PCREL, R_M32R_REL32 }, { BFD_RELOC_M32R_GOT24, R_M32R_GOT24 }, { BFD_RELOC_M32R_26_PLTREL, R_M32R_26_PLTREL }, @@ -1269,12 +1223,15 @@ 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 }, }; +#endif static reloc_howto_type * -bfd_elf32_bfd_reloc_type_lookup (abfd, code) - bfd *abfd ATTRIBUTE_UNUSED; - bfd_reloc_code_real_type code; +bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) { unsigned int i; @@ -1282,44 +1239,60 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) for (i = 0; i < sizeof (m32r_reloc_map_old) / sizeof (struct m32r_reloc_map); i++) - { - if (m32r_reloc_map_old[i].bfd_reloc_val == code) - return &m32r_elf_howto_table[m32r_reloc_map_old[i].elf_reloc_val]; - } + if (m32r_reloc_map_old[i].bfd_reloc_val == code) + return &m32r_elf_howto_table[m32r_reloc_map_old[i].elf_reloc_val]; + #else /* ! USE_M32R_OLD_RELOC */ for (i = 0; i < sizeof (m32r_reloc_map) / sizeof (struct m32r_reloc_map); i++) - { - if (m32r_reloc_map[i].bfd_reloc_val == code) - return &m32r_elf_howto_table[m32r_reloc_map[i].elf_reloc_val]; - } + if (m32r_reloc_map[i].bfd_reloc_val == code) + return &m32r_elf_howto_table[m32r_reloc_map[i].elf_reloc_val]; #endif return NULL; } +static reloc_howto_type * +bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (m32r_elf_howto_table) / sizeof (m32r_elf_howto_table[0]); + i++) + if (m32r_elf_howto_table[i].name != NULL + && strcasecmp (m32r_elf_howto_table[i].name, r_name) == 0) + return &m32r_elf_howto_table[i]; + + return NULL; +} + /* Set the howto pointer for an M32R ELF reloc. */ static void -m32r_info_to_howto_rel (abfd, cache_ptr, dst) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *cache_ptr; - Elf_Internal_Rela *dst; +m32r_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, + arelent *cache_ptr, + Elf_Internal_Rela *dst) { unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); - BFD_ASSERT (ELF32_R_TYPE(dst->r_info) <= (unsigned int) R_M32R_GNU_VTENTRY) + if (r_type > (unsigned int) R_M32R_GNU_VTENTRY) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%B: invalid M32R reloc number: %d"), abfd, r_type); + r_type = 0; + } cache_ptr->howto = &m32r_elf_howto_table[r_type]; } static void -m32r_info_to_howto (abfd, cache_ptr, dst) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *cache_ptr; - Elf_Internal_Rela *dst; +m32r_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + arelent *cache_ptr, + Elf_Internal_Rela *dst) { BFD_ASSERT ((ELF32_R_TYPE(dst->r_info) == (unsigned int) R_M32R_NONE) || ((ELF32_R_TYPE(dst->r_info) > (unsigned int) R_M32R_GNU_VTENTRY) @@ -1331,11 +1304,10 @@ m32r_info_to_howto (abfd, cache_ptr, dst) /* Given a BFD section, try to locate the corresponding ELF section index. */ -bfd_boolean -_bfd_m32r_elf_section_from_bfd_section (abfd, sec, retval) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec; - int *retval; +static bfd_boolean +_bfd_m32r_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + int *retval) { if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) { @@ -1357,14 +1329,10 @@ static asymbol *m32r_elf_scom_symbol_ptr; /* Handle the special M32R section numbers that a symbol may use. */ -void -_bfd_m32r_elf_symbol_processing (abfd, asym) - bfd *abfd ATTRIBUTE_UNUSED; - asymbol *asym; +static void +_bfd_m32r_elf_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym) { - elf_symbol_type *elfsym; - - elfsym = (elf_symbol_type *) asym; + elf_symbol_type *elfsym = (elf_symbol_type *) asym; switch (elfsym->internal_elf_sym.st_shndx) { @@ -1394,16 +1362,15 @@ _bfd_m32r_elf_symbol_processing (abfd, asym) linker sections. */ static bfd_boolean -m32r_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) - bfd *abfd; - struct bfd_link_info *info; - Elf_Internal_Sym *sym; - const char **namep; - flagword *flagsp ATTRIBUTE_UNUSED; - asection **secp; - bfd_vma *valp; +m32r_elf_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info, + Elf_Internal_Sym *sym, + const char **namep, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) { - if (! info->relocatable + if (! bfd_link_relocatable (info) && (*namep)[0] == '_' && (*namep)[1] == 'S' && strcmp (*namep, "_SDA_BASE_") == 0 && is_elf_hash_table (info->hash)) @@ -1418,17 +1385,17 @@ m32r_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) asection *s = bfd_get_section_by_name (abfd, ".sdata"); /* The following code was cobbled from elf32-ppc.c and elflink.c. */ - if (s == NULL) { flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - s = bfd_make_section_anyway (abfd, ".sdata"); + s = bfd_make_section_anyway_with_flags (abfd, ".sdata", + flags); if (s == NULL) return FALSE; - bfd_set_section_flags (abfd, s, flags); - bfd_set_section_alignment (abfd, s, 2); + if (! bfd_set_section_alignment (abfd, s, 2)) + return FALSE; } bh = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", @@ -1441,7 +1408,7 @@ m32r_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) BSF_GLOBAL, s, (bfd_vma) 32768, - (const char *) NULL, + NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) @@ -1469,19 +1436,17 @@ m32r_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) external symbol if we are producing relocatable output. */ static bfd_reloc_status_type -m32r_elf_final_sda_base (output_bfd, info, error_message, psb) - bfd *output_bfd; - struct bfd_link_info *info; - const char **error_message; - bfd_vma *psb; +m32r_elf_final_sda_base (bfd *output_bfd, + struct bfd_link_info *info, + const char **error_message, + bfd_vma *psb) { if (elf_gp (output_bfd) == 0) { struct bfd_link_hash_entry *h; h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", FALSE, FALSE, TRUE); - if (h != (struct bfd_link_hash_entry *) NULL - && h->type == bfd_link_hash_defined) + if (h != NULL && h->type == bfd_link_hash_defined) elf_gp (output_bfd) = (h->u.def.value + h->u.def.section->output_section->vma + h->u.def.section->output_offset); @@ -1549,11 +1514,6 @@ struct elf_m32r_link_hash_entry /* Track dynamic relocs copied for this symbol. */ struct elf_m32r_dyn_relocs *dyn_relocs; - -// bfd_signed_vma gotplt_refcount; - - /* Number of PC relative relocs copied for this symbol. */ - /* struct elf_m32r_pcrel_relocs_copied *pcrel_relocs_copied; FIXME */ }; /* m32r ELF linker hash table. */ @@ -1563,16 +1523,11 @@ struct elf_m32r_link_hash_table struct elf_link_hash_table root; /* Short-cuts to get to dynamic linker sections. */ - asection *sgot; - asection *sgotplt; - asection *srelgot; - asection *splt; - asection *srelplt; asection *sdynbss; asection *srelbss; - /* Small local sym to section mapping cache. */ - struct sym_sec_cache sym_sec; + /* Small local sym cache. */ + struct sym_cache sym_cache; }; /* Traverse an m32r ELF linker hash table. */ @@ -1580,141 +1535,89 @@ struct elf_m32r_link_hash_table #define m32r_elf_link_hash_traverse(table, func, info) \ (elf_link_hash_traverse \ (&(table)->root, \ - (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ + (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \ (info))) /* Get the m32r ELF linker hash table from a link_info structure. */ - #define m32r_elf_hash_table(p) \ - ((struct elf_m32r_link_hash_table *) ((p)->hash)) + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ + == M32R_ELF_DATA ? ((struct elf_m32r_link_hash_table *) ((p)->hash)) : NULL) /* Create an entry in an m32r ELF linker hash table. */ -static struct bfd_hash_entry * -m32r_elf_link_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, - const char * ); static struct bfd_hash_entry * -m32r_elf_link_hash_newfunc (entry, table, string) - struct bfd_hash_entry *entry; - struct bfd_hash_table *table; - const char *string; +m32r_elf_link_hash_newfunc (struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string) { struct elf_m32r_link_hash_entry *ret = (struct elf_m32r_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct elf_m32r_link_hash_entry *) NULL) - ret = ((struct elf_m32r_link_hash_entry *) - bfd_hash_allocate (table, - sizeof (struct elf_m32r_link_hash_entry))); - if (ret == (struct elf_m32r_link_hash_entry *) NULL) - return (struct bfd_hash_entry *) ret; + if (ret == NULL) + ret = bfd_hash_allocate (table, + sizeof (struct elf_m32r_link_hash_entry)); + if (ret == NULL) + return NULL; /* Call the allocation method of the superclass. */ ret = ((struct elf_m32r_link_hash_entry *) _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); - if (ret != (struct elf_m32r_link_hash_entry *) NULL) + if (ret != NULL) { struct elf_m32r_link_hash_entry *eh; eh = (struct elf_m32r_link_hash_entry *) ret; eh->dyn_relocs = NULL; -// eh->gotplt_refcount = 0; - /* eh->pcrel_relocs_copied = NULL; FIXME */ } return (struct bfd_hash_entry *) ret; } /* Create an m32r ELF linker hash table. */ -static struct bfd_link_hash_table *m32r_elf_link_hash_table_create (bfd *); static struct bfd_link_hash_table * -m32r_elf_link_hash_table_create (abfd) - bfd *abfd; +m32r_elf_link_hash_table_create (bfd *abfd) { struct elf_m32r_link_hash_table *ret; bfd_size_type amt = sizeof (struct elf_m32r_link_hash_table); - ret = (struct elf_m32r_link_hash_table *) bfd_malloc (amt); - if (ret == (struct elf_m32r_link_hash_table *) NULL) + ret = bfd_zmalloc (amt); + if (ret == NULL) return NULL; - if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, - m32r_elf_link_hash_newfunc)) + if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, + m32r_elf_link_hash_newfunc, + sizeof (struct elf_m32r_link_hash_entry), + M32R_ELF_DATA)) { free (ret); return NULL; } - ret->sgot = NULL; - ret->sgotplt = NULL; - ret->srelgot = NULL; - ret->splt = NULL; - ret->srelplt = NULL; - ret->sdynbss = NULL; - ret->srelbss = NULL; - ret->sym_sec.abfd = NULL; - return &ret->root.root; } -/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up - shortcuts to them in our hash table. */ -static bfd_boolean create_got_section (bfd *, struct bfd_link_info *); - -static bfd_boolean -create_got_section (dynobj, info) - bfd *dynobj; - struct bfd_link_info *info; -{ - struct elf_m32r_link_hash_table *htab; - - if (! _bfd_elf_create_got_section (dynobj, info)) - return FALSE; - - htab = m32r_elf_hash_table (info); - htab->sgot = bfd_get_section_by_name (dynobj, ".got"); - htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); - if (! htab->sgot || ! htab->sgotplt) - abort (); - - htab->srelgot = bfd_make_section (dynobj, ".rela.got"); - if (htab->srelgot == NULL - || ! bfd_set_section_flags (dynobj, htab->srelgot, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)) - || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) - return FALSE; - - return TRUE; -} - /* Create dynamic sections when linking against a dynamic object. */ static bfd_boolean -m32r_elf_create_dynamic_sections (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +m32r_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) { struct elf_m32r_link_hash_table *htab; flagword flags, pltflags; - register asection *s; + asection *s; const struct elf_backend_data *bed = get_elf_backend_data (abfd); int ptralign = 2; /* 32bit */ htab = m32r_elf_hash_table (info); + if (htab == NULL) + return FALSE; /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and .rel[a].bss sections. */ - flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); @@ -1725,10 +1628,9 @@ m32r_elf_create_dynamic_sections (abfd, info) if (bed->plt_readonly) pltflags |= SEC_READONLY; - s = bfd_make_section (abfd, ".plt"); - htab->splt = s; + s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags); + htab->root.splt = s; if (s == NULL - || ! bfd_set_section_flags (abfd, s, pltflags) || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) return FALSE; @@ -1738,58 +1640,35 @@ m32r_elf_create_dynamic_sections (abfd, info) .plt section. */ struct bfd_link_hash_entry *bh = NULL; struct elf_link_hash_entry *h; + if (! (_bfd_generic_link_add_one_symbol (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, - (bfd_vma) 0, (const char *) NULL, FALSE, + (bfd_vma) 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) return FALSE; h = (struct elf_link_hash_entry *) bh; - h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; + h->def_regular = 1; h->type = STT_OBJECT; + htab->root.hplt = h; - if (info->shared + if (bfd_link_pic (info) && ! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } - s = bfd_make_section (abfd, - bed->default_use_rela_p ? ".rela.plt" : ".rel.plt"); - htab->srelplt = s; + s = bfd_make_section_anyway_with_flags (abfd, + bed->default_use_rela_p + ? ".rela.plt" : ".rel.plt", + flags | SEC_READONLY); + htab->root.srelplt = s; if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; - if (htab->sgot == NULL - && ! create_got_section (abfd, info)) + if (htab->root.sgot == NULL + && !_bfd_elf_create_got_section (abfd, info)) return FALSE; - { - const char *secname; - char *relname; - flagword secflags; - asection *sec; - - for (sec = abfd->sections; sec; sec = sec->next) - { - secflags = bfd_get_section_flags (abfd, sec); - if ((secflags & (SEC_DATA | SEC_LINKER_CREATED)) - || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS)) - continue; - secname = bfd_get_section_name (abfd, sec); - relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6); - strcpy (relname, ".rela"); - strcat (relname, secname); - if (bfd_get_section_by_name (abfd, secname)) - continue; - s = bfd_make_section (abfd, relname); - if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) - || ! bfd_set_section_alignment (abfd, s, ptralign)) - return FALSE; - } - } - if (bed->want_dynbss) { /* The .dynbss section is a place to put symbols which are defined @@ -1798,10 +1677,10 @@ m32r_elf_create_dynamic_sections (abfd, info) image and use a R_*_COPY reloc to tell the dynamic linker to initialize them at run time. The linker script puts the .dynbss section into the .bss section of the final image. */ - s = bfd_make_section (abfd, ".dynbss"); + s = bfd_make_section_anyway_with_flags (abfd, ".dynbss", + SEC_ALLOC | SEC_LINKER_CREATED); htab->sdynbss = s; - if (s == NULL - || ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) + if (s == NULL) return FALSE; /* The .rel[a].bss section holds copy relocs. This section is not normally needed. We need to create it here, though, so that the @@ -1814,14 +1693,14 @@ m32r_elf_create_dynamic_sections (abfd, info) be needed, we can discard it later. We will never need this section when generating a shared object, since they do not use copy relocs. */ - if (! info->shared) + if (! bfd_link_pic (info)) { - s = bfd_make_section (abfd, - (bed->default_use_rela_p - ? ".rela.bss" : ".rel.bss")); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->default_use_rela_p + ? ".rela.bss" : ".rel.bss"), + flags | SEC_READONLY); htab->srelbss = s; if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; } @@ -1831,16 +1710,14 @@ m32r_elf_create_dynamic_sections (abfd, info) } /* Copy the extra info we tack onto an elf_link_hash_entry. */ -static void m32r_elf_copy_indirect_symbol (const struct elf_backend_data *, - struct elf_link_hash_entry *, - struct elf_link_hash_entry *); static void -m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed, +m32r_elf_copy_indirect_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *dir, struct elf_link_hash_entry *ind) { - struct elf_m32r_link_hash_entry *edir, *eind; + struct elf_m32r_link_hash_entry * edir; + struct elf_m32r_link_hash_entry * eind; edir = (struct elf_m32r_link_hash_entry *) dir; eind = (struct elf_m32r_link_hash_entry *) ind; @@ -1852,12 +1729,9 @@ m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed, struct elf_m32r_dyn_relocs **pp; struct elf_m32r_dyn_relocs *p; - if (ind->root.type == bfd_link_hash_indirect) - abort (); - - /* Add reloc counts against the weak sym to the strong sym + /* Add reloc counts against the indirect sym to the direct sym list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) + for (pp = &eind->dyn_relocs; (p = *pp) != NULL;) { struct elf_m32r_dyn_relocs *q; @@ -1879,13 +1753,7 @@ m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed, eind->dyn_relocs = NULL; } -// if (ind->root.type == bfd_link_hash_indirect -// && dir->got.refcount <= 0) -// { -// edir->tls_type = eind->tls_type; -// eind->tls_type = GOT_UNKNOWN; -// } - _bfd_elf_link_hash_copy_indirect (bed, dir, ind); + _bfd_elf_link_hash_copy_indirect (info, dir, ind); } @@ -1896,44 +1764,38 @@ m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed, understand. */ static bfd_boolean -m32r_elf_adjust_dynamic_symbol (info, h) - struct bfd_link_info *info; - struct elf_link_hash_entry *h; +m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) { struct elf_m32r_link_hash_table *htab; struct elf_m32r_link_hash_entry *eh; struct elf_m32r_dyn_relocs *p; bfd *dynobj; asection *s; - unsigned int power_of_two; #ifdef DEBUG_PIC -printf("m32r_elf_adjust_dynamic_symbol()\n"); + printf ("m32r_elf_adjust_dynamic_symbol()\n"); #endif dynobj = elf_hash_table (info)->dynobj; /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL - && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) - || h->weakdef != NULL - || ((h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_REF_REGULAR) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0))); - + && (h->needs_plt + || h->u.weakdef != NULL + || (h->def_dynamic + && h->ref_regular + && !h->def_regular))); /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later, when we know the address of the .got section. */ if (h->type == STT_FUNC - || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) + || h->needs_plt) { - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 + if (! bfd_link_pic (info) + && !h->def_dynamic + && !h->ref_dynamic && h->root.type != bfd_link_hash_undefweak && h->root.type != bfd_link_hash_undefined) { @@ -1943,7 +1805,7 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); a procedure linkage table, and we can just do a PCREL reloc instead. */ h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 0; } return TRUE; @@ -1954,12 +1816,12 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); /* 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->weakdef != NULL) + if (h->u.weakdef != NULL) { - BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined - || h->weakdef->root.type == bfd_link_hash_defweak); - h->root.u.def.section = h->weakdef->root.u.def.section; - h->root.u.def.value = h->weakdef->root.u.def.value; + 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; return TRUE; } @@ -1970,18 +1832,18 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ - if (info->shared) + if (bfd_link_pic (info)) return TRUE; /* If there are no references to this symbol that do not use the GOT, we don't need to generate a copy reloc. */ - if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) + if (!h->non_got_ref) return TRUE; /* If -z nocopyreloc was given, we won't generate them either. */ if (info->nocopyreloc) { - h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + h->non_got_ref = 0; return TRUE; } @@ -1998,7 +1860,7 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); the copy reloc. */ if (p == NULL) { - h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + h->non_got_ref = 0; return TRUE; } @@ -2013,6 +1875,9 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); same memory location for the variable. */ htab = m32r_elf_hash_table (info); + if (htab == NULL) + return FALSE; + s = htab->sdynbss; BFD_ASSERT (s != NULL); @@ -2020,47 +1885,24 @@ printf("m32r_elf_adjust_dynamic_symbol()\n"); to copy the initial value out of the dynamic object and into the runtime process image. We need to remember the offset into the .rela.bss section we are going to use. */ - if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) + if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) { asection *srel; srel = htab->srelbss; BFD_ASSERT (srel != NULL); srel->size += sizeof (Elf32_External_Rela); - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; - } - - /* We need to figure out the alignment required for this symbol. I - have no idea how ELF linkers handle this. */ - power_of_two = bfd_log2 (h->size); - if (power_of_two > 3) - power_of_two = 3; - - /* Apply the required alignment. */ - 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)) - return FALSE; + h->needs_copy = 1; } - /* Define the symbol as being at this point in the section. */ - h->root.u.def.section = s; - h->root.u.def.value = s->size; - - /* Increment the section size to make room for the symbol. */ - s->size += h->size; - - return TRUE; + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for dynamic relocs. */ static bfd_boolean -allocate_dynrelocs (h, inf) - struct elf_link_hash_entry *h; - PTR inf; +allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct bfd_link_info *info; struct elf_m32r_link_hash_table *htab; @@ -2070,26 +1912,12 @@ allocate_dynrelocs (h, inf) if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (h->root.type == bfd_link_hash_warning) - /* When warning symbols are created, they **replace** the "real" - entry in the hash table, thus we never get to see the real - symbol in a hash traversal. So look at it now. */ - h = (struct elf_link_hash_entry *) h->root.u.i.link; - info = (struct bfd_link_info *) inf; htab = m32r_elf_hash_table (info); + if (htab == NULL) + return FALSE; eh = (struct elf_m32r_link_hash_entry *) h; -// if ((h->got.refcount > 0 -// || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) -// && eh->gotplt_refcount > 0) -// { -// /* The symbol has been forced local, or we have some direct got refs, -// so treat all the gotplt refs as got refs. */ -// h->got.refcount += eh->gotplt_refcount; -// if (h->plt.refcount >= eh->gotplt_refcount) -// h->plt.refcount -= eh->gotplt_refcount; -// } if (htab->root.dynamic_sections_created && h->plt.refcount > 0) @@ -2097,15 +1925,15 @@ allocate_dynrelocs (h, inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)) + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) { - asection *s = htab->splt; + asection *s = htab->root.splt; /* If this is the first .plt entry, make room for the special first entry. */ @@ -2119,8 +1947,8 @@ allocate_dynrelocs (h, inf) location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + if (! bfd_link_pic (info) + && !h->def_regular) { h->root.u.def.section = s; h->root.u.def.value = h->plt.offset; @@ -2131,21 +1959,21 @@ allocate_dynrelocs (h, inf) /* 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->size += 4; + htab->root.sgotplt->size += 4; /* We also need to make an entry in the .rel.plt section. */ - htab->srelplt->size += sizeof (Elf32_External_Rela); + htab->root.srelplt->size += sizeof (Elf32_External_Rela); } else { h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 0; } } else { h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 0; } if (h->got.refcount > 0) @@ -2156,19 +1984,19 @@ allocate_dynrelocs (h, inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } - s = htab->sgot; + s = htab->root.sgot; 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->size += sizeof (Elf32_External_Rela); + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)) + htab->root.srelgot->size += sizeof (Elf32_External_Rela); } else h->got.offset = (bfd_vma) -1; @@ -2182,14 +2010,15 @@ allocate_dynrelocs (h, inf) space for pc-relative relocs that have become local due to symbol visibility changes. */ - if (info->shared) + if (bfd_link_pic (info)) { - if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 - && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 + if (h->def_regular + && (h->forced_local || info->symbolic)) { struct elf_m32r_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL;) { p->count -= p->pc_count; p->pc_count = 0; @@ -2199,6 +2028,24 @@ allocate_dynrelocs (h, inf) pp = &p->next; } } + + /* Also discard relocs on undefined weak syms with non-default + visibility. */ + if (eh->dyn_relocs != NULL + && h->root.type == bfd_link_hash_undefweak) + { + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + eh->dyn_relocs = NULL; + + /* Make sure undefined weak symbols are output as a dynamic + symbol in PIEs. */ + else if (h->dynindx == -1 + && !h->forced_local) + { + if (! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + } } else { @@ -2206,9 +2053,9 @@ allocate_dynrelocs (h, inf) symbols which turn out to need copy relocs or are not dynamic. */ - if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + if (!h->non_got_ref + && ((h->def_dynamic + && !h->def_regular) || (htab->root.dynamic_sections_created && (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefined)))) @@ -2216,7 +2063,7 @@ allocate_dynrelocs (h, inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; @@ -2242,19 +2089,15 @@ allocate_dynrelocs (h, inf) return TRUE; } + /* Find any dynamic relocs that apply to read-only sections. */ static bfd_boolean -readonly_dynrelocs (h, inf) - struct elf_link_hash_entry *h; - PTR inf; +readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) { struct elf_m32r_link_hash_entry *eh; struct elf_m32r_dyn_relocs *p; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - eh = (struct elf_m32r_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { @@ -2276,9 +2119,8 @@ readonly_dynrelocs (h, inf) /* Set the sizes of the dynamic sections. */ static bfd_boolean -m32r_elf_size_dynamic_sections (output_bfd, info) - bfd *output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; +m32r_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) { struct elf_m32r_link_hash_table *htab; bfd *dynobj; @@ -2287,19 +2129,22 @@ m32r_elf_size_dynamic_sections (output_bfd, info) bfd *ibfd; #ifdef DEBUG_PIC -printf("m32r_elf_size_dynamic_sections()\n"); + printf ("m32r_elf_size_dynamic_sections()\n"); #endif htab = m32r_elf_hash_table (info); + if (htab == NULL) + return FALSE; + dynobj = htab->root.dynobj; BFD_ASSERT (dynobj != NULL); if (htab->root.dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (! info->shared) + if (bfd_link_executable (info) && !info->nointerp) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_linker_section (dynobj, ".interp"); BFD_ASSERT (s != NULL); s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; @@ -2308,7 +2153,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); /* Set up .got offsets for local syms, and space for local dynamic relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { bfd_signed_vma *local_got; bfd_signed_vma *end_local_got; @@ -2353,15 +2198,15 @@ printf("m32r_elf_size_dynamic_sections()\n"); symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; locsymcount = symtab_hdr->sh_info; end_local_got = local_got + locsymcount; - s = htab->sgot; - srel = htab->srelgot; + s = htab->root.sgot; + srel = htab->root.srelgot; for (; local_got < end_local_got; ++local_got) { if (*local_got > 0) { *local_got = s->size; s->size += 4; - if (info->shared) + if (bfd_link_pic (info)) srel->size += sizeof (Elf32_External_Rela); } else @@ -2371,7 +2216,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); /* Allocate global sym .plt and .got entries, and space for global sym dynamic relocs. */ - elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info); + elf_link_hash_traverse (&htab->root, allocate_dynrelocs, info); /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ @@ -2381,16 +2226,17 @@ printf("m32r_elf_size_dynamic_sections()\n"); if ((s->flags & SEC_LINKER_CREATED) == 0) continue; - if (s == htab->splt - || s == htab->sgot - || s == htab->sgotplt) + if (s == htab->root.splt + || s == htab->root.sgot + || s == htab->root.sgotplt + || s == htab->sdynbss) { /* Strip this section if we don't need it; see the comment below. */ } - else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) + else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) { - if (s->size != 0 && s != htab->srelplt) + if (s->size != 0 && s != htab->root.srelplt) relocs = TRUE; /* We use the reloc_count field as a counter if we need @@ -2398,10 +2244,8 @@ printf("m32r_elf_size_dynamic_sections()\n"); s->reloc_count = 0; } else - { - /* It's not one of our sections, so don't allocate space. */ - continue; - } + /* It's not one of our sections, so don't allocate space. */ + continue; if (s->size == 0) { @@ -2414,16 +2258,19 @@ printf("m32r_elf_size_dynamic_sections()\n"); adjust_dynamic_symbol is called, and it is that function which decides whether anything needs to go into these sections. */ - _bfd_strip_section_from_output (info, s); + s->flags |= SEC_EXCLUDE; continue; } + if ((s->flags & SEC_HAS_CONTENTS) == 0) + continue; + /* Allocate memory for the section contents. We use bfd_zalloc here in case unused entries are not reclaimed before the 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->size); + s->contents = bfd_zalloc (dynobj, s->size); if (s->contents == NULL) return FALSE; } @@ -2438,13 +2285,13 @@ printf("m32r_elf_size_dynamic_sections()\n"); #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (! info->shared) + if (bfd_link_executable (info)) { if (! add_dynamic_entry (DT_DEBUG, 0)) return FALSE; } - if (htab->splt->size != 0) + if (htab->root.splt->size != 0) { if (! add_dynamic_entry (DT_PLTGOT, 0) || ! add_dynamic_entry (DT_PLTRELSZ, 0) @@ -2465,7 +2312,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) elf_link_hash_traverse (&htab->root, readonly_dynrelocs, - (PTR) info); + info); if ((info->flags & DF_TEXTREL) != 0) { @@ -2478,6 +2325,7 @@ printf("m32r_elf_size_dynamic_sections()\n"); return TRUE; } + /* Relocate an M32R/D ELF section. There is some attempt to make this function usable for many architectures, both for RELA and REL type relocs, if only to serve as a learning tool. @@ -2512,33 +2360,32 @@ printf("m32r_elf_size_dynamic_sections()\n"); accordingly. */ static bfd_boolean -m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, - contents, relocs, local_syms, local_sections) - bfd *output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - bfd_byte *contents; - Elf_Internal_Rela *relocs; - Elf_Internal_Sym *local_syms; - asection **local_sections; +m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); Elf_Internal_Rela *rel, *relend; /* Assume success. */ bfd_boolean ret = TRUE; - struct elf_m32r_link_hash_table *htab = m32r_elf_hash_table (info); - bfd *dynobj; bfd_vma *local_got_offsets; asection *sgot, *splt, *sreloc; + bfd_vma high_address = bfd_get_section_limit (input_bfd, input_section); + + if (htab == NULL) + return FALSE; - dynobj = htab->root.dynobj; local_got_offsets = elf_local_got_offsets (input_bfd); - sgot = htab->sgot; - splt = htab->splt; + sgot = htab->root.sgot; + splt = htab->root.splt; sreloc = NULL; rel = relocs; @@ -2555,6 +2402,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, `r_addend'. */ bfd_vma addend = rel->r_addend; bfd_vma offset = rel->r_offset; + bfd_vma relocation; Elf_Internal_Sym *sym; asection *sec; const char *sym_name; @@ -2566,15 +2414,15 @@ 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), - (int) r_type); + /* xgettext:c-format */ + _bfd_error_handler (_("%B: unknown relocation type %d"), + input_bfd, (int) r_type); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; } - if (r_type == R_M32R_GNU_VTENTRY + if ( r_type == R_M32R_GNU_VTENTRY || r_type == R_M32R_GNU_VTINHERIT || r_type == R_M32R_NONE || r_type == R_M32R_RELA_GNU_VTENTRY @@ -2587,31 +2435,154 @@ 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)) - { - /* This is a relocatable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - sec = NULL; - if (r_symndx >= symtab_hdr->sh_info) - { - /* External symbol. */ - continue; - } + sym = NULL; + sec = NULL; + h = NULL; + if (r_symndx < symtab_hdr->sh_info) + { /* Local symbol. */ sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; sym_name = ""; - /* STT_SECTION: symbol is associated with a section. */ - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) + + if (!use_rel) { - /* Symbol isn't associated with a section. Nothing to do. */ - continue; + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + addend = rel->r_addend; } + else + { + relocation = (sec->output_section->vma + + sec->output_offset + + sym->st_value); + } + } + else + { + /* External symbol. */ + relocation = 0; - sec = local_sections[r_symndx]; - addend += sec->output_offset + sym->st_value; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + + if (info->wrap_hash != NULL + && (input_section->flags & SEC_DEBUGGING) != 0) + h = ((struct elf_link_hash_entry *) + unwrap_hash_lookup (info, input_bfd, &h->root)); + + 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; + sym_name = h->root.root.string; + + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + { + bfd_boolean dyn; + sec = h->root.u.def.section; + + dyn = htab->root.dynamic_sections_created; + sec = h->root.u.def.section; + if (r_type == R_M32R_GOTPC24 + || (r_type == R_M32R_GOTPC_HI_ULO + || r_type == R_M32R_GOTPC_HI_SLO + || r_type == R_M32R_GOTPC_LO) + || (r_type == R_M32R_26_PLTREL + && h->plt.offset != (bfd_vma) -1) + || ((r_type == R_M32R_GOT24 + || r_type == R_M32R_GOT16_HI_ULO + || r_type == R_M32R_GOT16_HI_SLO + || r_type == R_M32R_GOT16_LO) + && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + bfd_link_pic (info), + h) + && (! bfd_link_pic (info) + || (! info->symbolic && h->dynindx != -1) + || !h->def_regular)) + || (bfd_link_pic (info) + && ((! info->symbolic && h->dynindx != -1) + || !h->def_regular) + && (((r_type == R_M32R_16_RELA + || r_type == R_M32R_32_RELA + || r_type == R_M32R_24_RELA + || r_type == R_M32R_HI16_ULO_RELA + || r_type == R_M32R_HI16_SLO_RELA + || r_type == R_M32R_LO16_RELA) + && !h->forced_local) + || r_type == R_M32R_REL32 + || r_type == R_M32R_10_PCREL_RELA + || r_type == R_M32R_18_PCREL_RELA + || r_type == R_M32R_26_PCREL_RELA) + && ((input_section->flags & SEC_ALLOC) != 0 + /* DWARF will emit R_M32R_16(24,32) relocations + in its sections against symbols defined + externally in shared libraries. We can't do + anything with them here. */ + || ((input_section->flags & SEC_DEBUGGING) != 0 + && h->def_dynamic)))) + { + /* In these cases, we don't need the relocation + value. We check specially because in some + obscure cases sec->output_section will be NULL. */ + } + else if (sec->output_section != NULL) + relocation = (h->root.u.def.value + + sec->output_section->vma + + sec->output_offset); + else if (!bfd_link_relocatable (info) + && (_bfd_elf_section_offset (output_bfd, info, + input_section, + rel->r_offset) + != (bfd_vma) -1)) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + input_bfd, + input_section, + (long) rel->r_offset, + howto->name, + h->root.root.string); + } + } + else if (h->root.type == bfd_link_hash_undefweak) + ; + else if (info->unresolved_syms_in_objects == RM_IGNORE + && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) + ; + else if (!bfd_link_relocatable (info)) + (*info->callbacks->undefined_symbol) + (info, h->root.root.string, input_bfd, + input_section, offset, + (info->unresolved_syms_in_objects == RM_GENERATE_ERROR + || ELF_ST_VISIBILITY (h->other))); + } + + if (sec != NULL && discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, 1, relend, howto, 0, contents); + + if (bfd_link_relocatable (info) && !use_rel) + { + /* This is a relocatable link. We don't have to change + anything, unless the reloc is against a section symbol, + in which case we have to adjust according to where the + section symbol winds up in the output section. */ + if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + rel->r_addend += sec->output_offset; + continue; + } + + if (bfd_link_relocatable (info) && use_rel) + { + /* This is a relocatable link. We don't have to change + anything, unless the reloc is against a section symbol, + in which case we have to adjust according to where the + section symbol winds up in the output section. */ + if (sym == NULL || ELF_ST_TYPE (sym->st_info) != STT_SECTION) + continue; + + addend += sec->output_offset; /* If partial_inplace, we need to store any additional addend back in the section. */ @@ -2649,146 +2620,8 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, } else { - bfd_vma relocation; - bfd_size_type sz; - - /* This is a final link. */ - sym = NULL; - sec = NULL; - h = NULL; - - if (r_symndx < symtab_hdr->sh_info) - { - /* Local symbol. */ - sym = local_syms + r_symndx; - sec = local_sections[r_symndx]; - sym_name = ""; - - if (use_rel == FALSE) - { - relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); - addend = rel->r_addend; - - if (info->relocatable) - { - /* This is a relocatable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) - rel->r_addend += sec->output_offset + sym->st_value; - - continue; - } - } - else - { - relocation = (sec->output_section->vma - + sec->output_offset - + sym->st_value); - } - } - else - { - /* External symbol. */ - if (info->relocatable && (use_rel == FALSE)) - continue; - - h = sym_hashes[r_symndx - symtab_hdr->sh_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; - sym_name = h->root.root.string; - - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - bfd_boolean dyn; - sec = h->root.u.def.section; - - dyn = htab->root.dynamic_sections_created; - sec = h->root.u.def.section; - if (r_type == R_M32R_GOTPC24 - || (r_type == R_M32R_GOTPC_HI_ULO - || r_type == R_M32R_GOTPC_HI_SLO - || r_type == R_M32R_GOTPC_LO) - || (r_type == R_M32R_26_PLTREL - && h->plt.offset != (bfd_vma) -1) - || ((r_type == R_M32R_GOT24 - || r_type == R_M32R_GOT16_HI_ULO - || r_type == R_M32R_GOT16_HI_SLO - || r_type == R_M32R_GOT16_LO) - && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, - info->shared, h) - && (! info->shared - || (! info->symbolic && h->dynindx != -1) - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)) - || (info->shared - && ((! info->symbolic && h->dynindx != -1) - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0) - && (((r_type == R_M32R_16_RELA - || r_type == R_M32R_32_RELA - || r_type == R_M32R_24_RELA - || r_type == R_M32R_HI16_ULO_RELA - || r_type == R_M32R_HI16_SLO_RELA - || r_type == R_M32R_LO16_RELA) - && (h->elf_link_hash_flags - & ELF_LINK_FORCED_LOCAL) == 0) - || r_type == R_M32R_10_PCREL_RELA - || r_type == R_M32R_18_PCREL_RELA - || r_type == R_M32R_26_PCREL_RELA) - && ((input_section->flags & SEC_ALLOC) != 0 - /* DWARF will emit R_M32R_16(24,32) relocations - in its sections against symbols defined - externally in shared libraries. We can't do - anything with them here. */ - || ((input_section->flags & SEC_DEBUGGING) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))) - { - /* In these cases, we don't need the relocation - value. We check specially because in some - obscure cases sec->output_section will be NULL. */ - relocation = 0; - } - else if (sec->output_section == NULL) - { - (*_bfd_error_handler) - (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), - bfd_get_filename (input_bfd), h->root.root.string, - bfd_get_section_name (input_bfd, input_section)); - - relocation = 0; - } - else - relocation = (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset); - } - else if (h->root.type == bfd_link_hash_undefweak) - relocation = 0; - else if (info->unresolved_syms_in_objects == RM_IGNORE - && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) - relocation = 0; - else - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, offset, - (info->unresolved_syms_in_objects == RM_GENERATE_ERROR - || ELF_ST_VISIBILITY (h->other))))) - return FALSE; - relocation = 0; - } - } - /* Sanity check the address. */ - sz = (input_section->rawsize - ? input_section->rawsize - : input_section->size); - if (offset > input_section->size) + if (offset > high_address) { r = bfd_reloc_outofrange; goto check_reloc; @@ -2796,6 +2629,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_ @@ -2844,12 +2702,14 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT (off != (bfd_vma) -1); dyn = htab->root.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - || (info->shared + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + bfd_link_pic (info), + h) + || (bfd_link_pic (info) && (info->symbolic || h->dynindx == -1 - || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + || h->forced_local) + && h->def_regular)) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined @@ -2894,14 +2754,14 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, { bfd_put_32 (output_bfd, relocation, sgot->contents + off); - if (info->shared) + if (bfd_link_pic (info)) { asection *srelgot; Elf_Internal_Rela outrel; /* We need to generate a R_M32R_RELATIVE reloc for the dynamic linker. */ - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + srelgot = htab->root.srelgot; BFD_ASSERT (srelgot != NULL); outrel.r_offset = (sgot->output_section->vma @@ -2910,7 +2770,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, outrel.r_info = ELF32_R_INFO (0, R_M32R_RELATIVE); outrel.r_addend = relocation; loc = srelgot->contents; - loc += srelgot->reloc_count * sizeof(Elf32_External_Rela); + loc += srelgot->reloc_count * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &outrel,loc); ++srelgot->reloc_count; } @@ -2936,19 +2796,14 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (h == NULL) break; - //if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL - // || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) - // break; - if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) + if (h->forced_local) break; if (h->plt.offset == (bfd_vma) -1) - { - /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code, or when - using -Bsymbolic. */ - break; - } + /* We didn't make a PLT entry for this symbol. This + happens when statically linking PIC code, or when + using -Bsymbolic. */ + break; relocation = (splt->output_section->vma + splt->output_offset @@ -2956,31 +2811,30 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, break; case R_M32R_HI16_SLO_RELA: - { - if ((relocation + rel->r_addend) & 0x8000) - { - rel->r_addend += 0x10000; - } - } + if ((relocation + rel->r_addend) & 0x8000) + rel->r_addend += 0x10000; /* Fall through. */ + case R_M32R_16_RELA: case R_M32R_24_RELA: case R_M32R_32_RELA: + case R_M32R_REL32: + case R_M32R_10_PCREL_RELA: case R_M32R_18_PCREL_RELA: 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 + if (bfd_link_pic (info) + && r_symndx != STN_UNDEF && (input_section->flags & SEC_ALLOC) != 0 - && ((r_type != R_M32R_18_PCREL_RELA - && r_type != R_M32R_26_PCREL_RELA) + && (( r_type != R_M32R_10_PCREL_RELA + && r_type != R_M32R_18_PCREL_RELA + && r_type != R_M32R_26_PCREL_RELA + && r_type != R_M32R_REL32) || (h != NULL && h->dynindx != -1 && (! info->symbolic - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || !h->def_regular)))) { Elf_Internal_Rela outrel; bfd_boolean skip, relocate; @@ -2989,25 +2843,12 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - if (sreloc == NULL) { - const char *name; - - name = (bfd_elf_string_from_elf_section - (input_bfd, - elf_elfheader (input_bfd)->e_shstrndx, - elf_section_data (input_section)->rel_hdr.sh_name)); - if (name == NULL) - return FALSE; - - BFD_ASSERT (strncmp (name, ".rela", 5) == 0 - && strcmp (bfd_get_section_name (input_bfd, - input_section), - name + 5) == 0); - - sreloc = bfd_get_section_by_name (dynobj, name); - BFD_ASSERT (sreloc != NULL); + sreloc = _bfd_elf_get_dynamic_reloc_section + (input_bfd, input_section, /*rela?*/ TRUE); + if (sreloc == NULL) + return FALSE; } skip = FALSE; @@ -3020,14 +2861,16 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (outrel.r_offset == (bfd_vma) -1) skip = TRUE; else if (outrel.r_offset == (bfd_vma) -2) - skip = TRUE, relocate = TRUE; + skip = relocate = TRUE; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); if (skip) memset (&outrel, 0, sizeof outrel); - else if (r_type == R_M32R_18_PCREL_RELA - || r_type == R_M32R_26_PCREL_RELA) + else if ( r_type == R_M32R_10_PCREL_RELA + || r_type == R_M32R_18_PCREL_RELA + || r_type == R_M32R_26_PCREL_RELA + || r_type == R_M32R_REL32) { BFD_ASSERT (h != NULL && h->dynindx != -1); outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); @@ -3039,8 +2882,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, become local. */ if (h == NULL || ((info->symbolic || h->dynindx == -1) - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) != 0)) + && h->def_regular)) { relocate = TRUE; outrel.r_info = ELF32_R_INFO (0, R_M32R_RELATIVE); @@ -3055,7 +2897,7 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, } loc = sreloc->contents; - loc += sreloc->reloc_count * sizeof(Elf32_External_Rela); + loc += sreloc->reloc_count * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &outrel,loc); ++sreloc->reloc_count; @@ -3065,8 +2907,11 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, an addend for the dynamic reloc. */ if (! relocate) continue; + break; } - break; + else if (r_type != R_M32R_10_PCREL_RELA) + break; + /* Fall through. */ case (int) R_M32R_10_PCREL : r = m32r_elf_do_10_pcrel_reloc (input_bfd, howto, input_section, @@ -3103,14 +2948,15 @@ 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; BFD_ASSERT (sec != NULL); - name = bfd_get_section_name (abfd, sec); + name = bfd_get_section_name (sec->owner, sec); - if (strcmp (name, ".sdata") == 0 + if ( strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0 || strcmp (name, ".scommon") == 0) { @@ -3133,18 +2979,19 @@ 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), + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: The target (%s) of an %s relocation is in the wrong section (%A)"), + input_bfd, sym_name, m32r_elf_howto_table[(int) r_type].name, - bfd_get_section_name (abfd, sec)); + sec); /*bfd_set_error (bfd_error_bad_value); ??? why? */ ret = FALSE; continue; } } - /* fall through */ + /* Fall through. */ default : /* OLD_M32R_RELOC */ @@ -3183,17 +3030,14 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, switch (r) { case bfd_reloc_overflow: - if (! ((*info->callbacks->reloc_overflow) - (info, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, offset))) - return FALSE; + (*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, offset); break; case bfd_reloc_undefined: - if (! ((*info->callbacks->undefined_symbol) - (info, name, input_bfd, input_section, - offset, TRUE))) - return FALSE; + (*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, offset, TRUE); break; case bfd_reloc_outofrange: @@ -3213,10 +3057,8 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* fall through */ common_error: - if (!((*info->callbacks->warning) - (info, errmsg, name, input_bfd, input_section, - offset))) - return FALSE; + (*info->callbacks->warning) (info, errmsg, name, input_bfd, + input_section, offset); break; } } @@ -3227,23 +3069,23 @@ m32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ + static bfd_boolean -m32r_elf_finish_dynamic_symbol (output_bfd, info, h, sym) - bfd *output_bfd; - struct bfd_link_info *info; - struct elf_link_hash_entry *h; - Elf_Internal_Sym *sym; +m32r_elf_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { struct elf_m32r_link_hash_table *htab; - bfd *dynobj; bfd_byte *loc; #ifdef DEBUG_PIC -printf("m32r_elf_finish_dynamic_symbol()\n"); + printf ("m32r_elf_finish_dynamic_symbol()\n"); #endif htab = m32r_elf_hash_table (info); - dynobj = htab->root.dynobj; + if (htab == NULL) + return FALSE; if (h->plt.offset != (bfd_vma) -1) { @@ -3260,9 +3102,9 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); BFD_ASSERT (h->dynindx != -1); - splt = htab->splt; - sgot = htab->sgotplt; - srela = htab->srelplt; + splt = htab->root.splt; + sgot = htab->root.sgotplt; + srela = htab->root.srelplt; BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL); /* Get the index in the procedure linkage table which @@ -3277,7 +3119,7 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); got_offset = (plt_index + 3) * 4; /* Fill in the entry in the procedure linkage table. */ - if (! info->shared) + if (! bfd_link_pic (info)) { bfd_put_32 (output_bfd, (PLT_ENTRY_WORD0b @@ -3336,10 +3178,10 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); rela.r_info = ELF32_R_INFO (h->dynindx, R_M32R_JMP_SLOT); rela.r_addend = 0; loc = srela->contents; - loc += plt_index * sizeof(Elf32_External_Rela); + loc += plt_index * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); - if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. */ @@ -3356,8 +3198,8 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); /* This symbol has an entry in the global offset table. Set it up. */ - sgot = htab->sgot; - srela = htab->srelgot; + sgot = htab->root.sgot; + srela = htab->root.srelgot; BFD_ASSERT (sgot != NULL && srela != NULL); rela.r_offset = (sgot->output_section->vma @@ -3369,11 +3211,11 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); the symbol was forced to be local because of a version file. The entry in the global offset table will already have been initialized in the relocate_section function. */ - if (info->shared + if (bfd_link_pic (info) && (info->symbolic || h->dynindx == -1 - || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) + || h->forced_local) + && h->def_regular) { rela.r_info = ELF32_R_INFO (0, R_M32R_RELATIVE); rela.r_addend = (h->root.u.def.value @@ -3382,19 +3224,19 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); } else { - BFD_ASSERT((h->got.offset & 1) == 0); + BFD_ASSERT ((h->got.offset & 1) == 0); bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_M32R_GLOB_DAT); rela.r_addend = 0; } loc = srela->contents; - loc += srela->reloc_count * sizeof(Elf32_External_Rela); + loc += srela->reloc_count * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); ++srela->reloc_count; } - if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) + if (h->needs_copy) { asection *s; Elf_Internal_Rela rela; @@ -3405,8 +3247,7 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak)); - s = bfd_get_section_by_name (h->root.u.def.section->owner, - ".rela.bss"); + s = bfd_get_linker_section (htab->root.dynobj, ".rela.bss"); BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value @@ -3415,14 +3256,13 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); rela.r_info = ELF32_R_INFO (h->dynindx, R_M32R_COPY); rela.r_addend = 0; loc = s->contents; - loc += s->reloc_count * sizeof(Elf32_External_Rela); + loc += s->reloc_count * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); ++s->reloc_count; } /* Mark some specially defined symbols as absolute. */ - if (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + if (h == htab->root.hdynamic || h == htab->root.hgot) sym->st_shndx = SHN_ABS; return TRUE; @@ -3432,9 +3272,8 @@ printf("m32r_elf_finish_dynamic_symbol()\n"); /* Finish up the dynamic sections. */ static bfd_boolean -m32r_elf_finish_dynamic_sections (output_bfd, info) - bfd *output_bfd; - struct bfd_link_info *info; +m32r_elf_finish_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) { struct elf_m32r_link_hash_table *htab; bfd *dynobj; @@ -3442,14 +3281,17 @@ m32r_elf_finish_dynamic_sections (output_bfd, info) asection *sgot; #ifdef DEBUG_PIC -printf("m32r_elf_finish_dynamic_sections()\n"); + printf ("m32r_elf_finish_dynamic_sections()\n"); #endif htab = m32r_elf_hash_table (info); + if (htab == NULL) + return FALSE; + dynobj = htab->root.dynobj; - sgot = htab->sgotplt; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sgot = htab->root.sgotplt; + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); if (htab->root.dynamic_sections_created) { @@ -3464,7 +3306,6 @@ printf("m32r_elf_finish_dynamic_sections()\n"); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; - const char *name; asection *s; bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); @@ -3475,50 +3316,28 @@ printf("m32r_elf_finish_dynamic_sections()\n"); break; case DT_PLTGOT: - name = ".got"; - s = htab->sgot->output_section; + s = htab->root.sgotplt; goto get_vma; case DT_JMPREL: - name = ".rela.plt"; - s = htab->srelplt->output_section; + s = htab->root.srelplt; get_vma: - BFD_ASSERT (s != NULL); - dyn.d_un.d_ptr = s->vma; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; case DT_PLTRELSZ: - s = htab->srelplt->output_section; - BFD_ASSERT (s != NULL); + s = htab->root.srelplt; dyn.d_un.d_val = s->size; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; - - case DT_RELASZ: - /* My reading of the SVR4 ABI indicates that the - procedure linkage table relocs (DT_JMPREL) should be - included in the overall relocs (DT_RELA). This is - what Solaris does. However, UnixWare can not handle - that case. Therefore, we override the DT_RELASZ entry - here to make it not include the JMPREL relocs. Since - the linker script arranges for .rela.plt to follow all - other relocation sections, we don't have to worry - about changing the DT_RELA entry. */ - if (htab->srelplt != NULL) - { - s = htab->srelplt->output_section; - dyn.d_un.d_val -= s->size; - } - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); - break; } } /* Fill in the first entry in the procedure linkage table. */ - splt = htab->splt; + splt = htab->root.splt; if (splt && splt->size > 0) { - if (info->shared) + if (bfd_link_pic (info)) { bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD0, splt->contents); bfd_put_32 (output_bfd, PLT0_PIC_ENTRY_WORD1, splt->contents + 4); @@ -3565,546 +3384,11 @@ printf("m32r_elf_finish_dynamic_sections()\n"); return TRUE; } - -#if 0 /* relaxing not supported yet */ - -/* This function handles relaxing for the m32r. - Relaxing on the m32r is tricky because of instruction alignment - requirements (4 byte instructions must be aligned on 4 byte boundaries). - - The following relaxing opportunities are handled: - - seth/add3/jl -> bl24 or bl8 - seth/add3 -> ld24 - - It would be nice to handle bl24 -> bl8 but given: - - - 4 byte insns must be on 4 byte boundaries - - branch instructions only branch to insns on 4 byte boundaries - - this isn't much of a win because the insn in the 2 "deleted" bytes - must become a nop. With some complexity some real relaxation could be - done but the frequency just wouldn't make it worth it; it's better to - try to do all the code compaction one can elsewhere. - When the chip supports parallel 16 bit insns, things may change. -*/ - -static bfd_boolean -m32r_elf_relax_section (abfd, sec, link_info, again) - bfd *abfd; - asection *sec; - struct bfd_link_info *link_info; - bfd_boolean *again; -{ - Elf_Internal_Shdr *symtab_hdr; - /* The Rela structures are used here because that's what - _bfd_elf_link_read_relocs uses [for convenience - it sets the addend - field to 0]. */ - Elf_Internal_Rela *internal_relocs = NULL; - Elf_Internal_Rela *irel, *irelend; - bfd_byte *contents = NULL; - Elf_Internal_Sym *isymbuf = NULL; - - /* Assume nothing changes. */ - *again = FALSE; - - /* We don't have to do anything for a relocatable link, if - this section does not have relocs, or if this is not a - code section. */ - if (link_info->relocatable - || (sec->flags & SEC_RELOC) == 0 - || sec->reloc_count == 0 - || (sec->flags & SEC_CODE) == 0 - || 0 /* FIXME: check SHF_M32R_CAN_RELAX */) - return TRUE; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - - /* Get a copy of the native relocations. */ - internal_relocs = (_bfd_elf_link_read_relocs - (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, - link_info->keep_memory)); - if (internal_relocs == NULL) - goto error_return; - - /* Walk through them looking for relaxing opportunities. */ - irelend = internal_relocs + sec->reloc_count; - for (irel = internal_relocs; irel < irelend; irel++) - { - bfd_vma symval; - - /* If this isn't something that can be relaxed, then ignore - this reloc. */ - if (ELF32_R_TYPE (irel->r_info) != (int) R_M32R_HI16_SLO) - continue; - - /* Get the section contents if we haven't done so already. */ - if (contents == NULL) - { - /* Get cached copy if it exists. */ - if (elf_section_data (sec)->this_hdr.contents != NULL) - contents = elf_section_data (sec)->this_hdr.contents; - else - { - /* Go get them off disk. */ - if (!bfd_malloc_and_get_section (abfd, sec, &contents)) - goto error_return; - } - } - - /* Read this BFD's local 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 error_return; - } - - /* Get the value of the symbol referred to by the reloc. */ - if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) - { - /* A local symbol. */ - Elf_Internal_Sym *isym; - asection *sym_sec; - - isym = isymbuf + ELF32_R_SYM (irel->r_info), - sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); - symval = (isym->st_value - + sym_sec->output_section->vma - + sym_sec->output_offset); - } - else - { - unsigned long indx; - struct elf_link_hash_entry *h; - - /* An external symbol. */ - indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; - h = elf_sym_hashes (abfd)[indx]; - BFD_ASSERT (h != NULL); - if (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - { - /* This appears to be a reference to an undefined - symbol. Just ignore it--it will be caught by the - regular reloc processing. */ - continue; - } - - symval = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - } - - /* 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. */ - - /* Try to change a seth/add3/jl subroutine call to bl24 or bl8. - This sequence is generated by the compiler when compiling in - 32 bit mode. Also look for seth/add3 -> ld24. */ - - if (ELF32_R_TYPE (irel->r_info) == (int) R_M32R_HI16_SLO) - { - Elf_Internal_Rela *nrel; - bfd_vma pc = (sec->output_section->vma + sec->output_offset - + irel->r_offset); - bfd_signed_vma pcrel_value = symval - pc; - unsigned int code,reg; - int addend,nop_p,bl8_p,to_delete; - - /* The tests are ordered so that we get out as quickly as possible - if this isn't something we can relax, taking into account that - we are looking for two separate possibilities (jl/ld24). */ - - /* Do nothing if no room in the section for this to be what we're - looking for. */ - if (irel->r_offset > sec->size - 8) - continue; - - /* Make sure the next relocation applies to the next - instruction and that it's the add3's reloc. */ - nrel = irel + 1; - if (nrel == irelend - || irel->r_offset + 4 != nrel->r_offset - || ELF32_R_TYPE (nrel->r_info) != (int) R_M32R_LO16) - continue; - - /* See if the instructions are seth/add3. */ - /* FIXME: This is where macros from cgen can come in. */ - code = bfd_get_16 (abfd, contents + irel->r_offset + 0); - if ((code & 0xf0ff) != 0xd0c0) - continue; /* not seth rN,foo */ - reg = (code & 0x0f00) >> 8; - code = bfd_get_16 (abfd, contents + irel->r_offset + 4); - if (code != (0x80a0 | reg | (reg << 8))) - continue; /* not add3 rN,rN,foo */ - - /* At this point we've confirmed we have seth/add3. Now check - whether the next insn is a jl, in which case try to change this - to bl24 or bl8. */ - - /* Ensure the branch target is in range. - The bl24 instruction has a 24 bit operand which is the target - address right shifted by 2, giving a signed range of 26 bits. - Note that 4 bytes are added to the high value because the target - will be at least 4 bytes closer if we can relax. It'll actually - be 4 or 8 bytes closer, but we don't know which just yet and - the difference isn't significant enough to worry about. */ -#if !USE_REL /* put in for learning purposes */ - pcrel_value += irel->r_addend; -#else - addend = bfd_get_signed_16 (abfd, contents + irel->r_offset + 2); - pcrel_value += addend; -#endif - - 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->size - 12) - /* Ensure the next insn is "jl rN". */ - && ((code = bfd_get_16 (abfd, contents + irel->r_offset + 8)), - code != (0x1ec0 | reg))) - { - /* We can relax to bl24/bl8. */ - - /* See if there's a nop following the jl. - Also see if we can use a bl8 insn. */ - code = bfd_get_16 (abfd, contents + irel->r_offset + 10); - nop_p = (code & 0x7fff) == NOP_INSN; - bl8_p = pcrel_value >= -0x200 && pcrel_value < 0x200; - - if (bl8_p) - { - /* Change "seth rN,foo" to "bl8 foo || nop". - We OR in CODE just in case it's not a nop (technically, - CODE currently must be a nop, but for cleanness we - allow it to be anything). */ -#if !USE_REL /* put in for learning purposes */ - code = 0x7e000000 | MAKE_PARALLEL (code); -#else - code = (0x7e000000 + (((addend >> 2) & 0xff) << 16)) | MAKE_PARALLEL (code); -#endif - to_delete = 8; - } - else - { - /* Change the seth rN,foo to a bl24 foo. */ -#if !USE_REL /* put in for learning purposes */ - code = 0xfe000000; -#else - code = 0xfe000000 + ((addend >> 2) & 0xffffff); -#endif - to_delete = nop_p ? 8 : 4; - } - - bfd_put_32 (abfd, code, contents + irel->r_offset); - - /* Set the new reloc type. */ - irel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), - bl8_p ? R_M32R_10_PCREL : R_M32R_26_PCREL); - - /* Delete the add3 reloc by making it a null reloc. */ - nrel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), - R_M32R_NONE); - } - else if (addend >= 0 - && symval + addend <= 0xffffff) - { - /* We can relax to ld24. */ - - code = 0xe0000000 | (reg << 24) | (addend & 0xffffff); - bfd_put_32 (abfd, code, contents + irel->r_offset); - to_delete = 4; - /* Tell the following code a nop filler isn't needed. */ - nop_p = 1; - } - else - { - /* Can't do anything here. */ - continue; - } - - /* Note that we've changed the relocs, section contents, etc. */ - elf_section_data (sec)->relocs = internal_relocs; - elf_section_data (sec)->this_hdr.contents = contents; - symtab_hdr->contents = (unsigned char *) isymbuf; - - /* Delete TO_DELETE bytes of data. */ - if (!m32r_elf_relax_delete_bytes (abfd, sec, - irel->r_offset + 4, to_delete)) - goto error_return; - - /* Now that the following bytes have been moved into place, see if - we need to replace the jl with a nop. This happens when we had - to use a bl24 insn and the insn following the jl isn't a nop. - Technically, this situation can't happen (since the insn can - never be executed) but to be clean we do this. When the chip - supports parallel 16 bit insns things may change. - We don't need to do this in the case of relaxing to ld24, - and the above code sets nop_p so this isn't done. */ - if (! nop_p && to_delete == 4) - bfd_put_16 (abfd, NOP_INSN, contents + irel->r_offset + 4); - - /* That will change things, so we should relax again. - Note that this is not required, and it may be slow. */ - *again = TRUE; - - continue; - } - - /* loop to try the next reloc */ - } - - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - { - if (! link_info->keep_memory) - free (isymbuf); - else - { - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = (unsigned char *) isymbuf; - } - } - - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - { - if (! link_info->keep_memory) - free (contents); - else - { - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; - } - } - - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) - free (internal_relocs); - - return TRUE; - - error_return: - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - free (isymbuf); - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) - free (contents); - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) - free (internal_relocs); - - return FALSE; -} - -/* Delete some bytes from a section while relaxing. */ - -static bfd_boolean -m32r_elf_relax_delete_bytes (abfd, sec, addr, count) - bfd *abfd; - asection *sec; - bfd_vma addr; - int count; -{ - Elf_Internal_Shdr *symtab_hdr; - int shndx; - bfd_byte *contents; - Elf_Internal_Rela *irel, *irelend; - Elf_Internal_Rela *irelalign; - bfd_vma toaddr; - Elf_Internal_Sym *isym, *isymend; - struct elf_link_hash_entry **sym_hashes; - struct elf_link_hash_entry **end_hashes; - unsigned int symcount; - - shndx = _bfd_elf_section_from_bfd_section (abfd, sec); - - contents = elf_section_data (sec)->this_hdr.contents; - - /* The deletion must stop at the next ALIGN reloc for an aligment - power larger than the number of bytes we are deleting. */ - - irelalign = NULL; - 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->size -= count; - - /* Adjust all the relocs. */ - for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) - { - /* Get the new reloc address. */ - if ((irel->r_offset > addr - && irel->r_offset < toaddr)) - irel->r_offset -= count; - } - - /* Adjust the local symbols defined in this section. */ - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - isym = (Elf_Internal_Sym *) symtab_hdr->contents; - for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) - { - if (isym->st_shndx == shndx - && isym->st_value > addr - && isym->st_value < toaddr) - isym->st_value -= count; - } - - /* Now adjust the global symbols defined in this section. */ - symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) - - symtab_hdr->sh_info); - sym_hashes = elf_sym_hashes (abfd); - end_hashes = sym_hashes + symcount; - for (; sym_hashes < end_hashes; sym_hashes++) - { - struct elf_link_hash_entry *sym_hash = *sym_hashes; - - if ((sym_hash->root.type == bfd_link_hash_defined - || sym_hash->root.type == bfd_link_hash_defweak) - && sym_hash->root.u.def.section == sec - && sym_hash->root.u.def.value > addr - && sym_hash->root.u.def.value < toaddr) - { - sym_hash->root.u.def.value -= count; - } - } - - return TRUE; -} - -/* This is a version of bfd_generic_get_relocated_section_contents - which uses m32r_elf_relocate_section. */ - -static bfd_byte * -m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, - data, relocatable, symbols) - bfd *output_bfd; - struct bfd_link_info *link_info; - struct bfd_link_order *link_order; - bfd_byte *data; - bfd_boolean relocatable; - asymbol **symbols; -{ - Elf_Internal_Shdr *symtab_hdr; - asection *input_section = link_order->u.indirect.section; - bfd *input_bfd = input_section->owner; - asection **sections = NULL; - Elf_Internal_Rela *internal_relocs = NULL; - Elf_Internal_Sym *isymbuf = NULL; - bfd_size_type amt; - - /* We only need to handle the case of relaxing, or of having a - particular set of section contents, specially. */ - if (relocatable - || elf_section_data (input_section)->this_hdr.contents == NULL) - return bfd_generic_get_relocated_section_contents (output_bfd, link_info, - link_order, data, - relocatable, - symbols); - - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - - memcpy (data, elf_section_data (input_section)->this_hdr.contents, - input_section->size); - - if ((input_section->flags & SEC_RELOC) != 0 - && input_section->reloc_count > 0) - { - Elf_Internal_Sym *isymp; - asection **secpp; - Elf32_External_Sym *esym, *esymend; - - internal_relocs = (_bfd_elf_link_read_relocs - (input_bfd, input_section, (PTR) NULL, - (Elf_Internal_Rela *) NULL, FALSE)); - if (internal_relocs == NULL) - goto error_return; - - if (symtab_hdr->sh_info != 0) - { - isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; - if (isymbuf == NULL) - isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, - symtab_hdr->sh_info, 0, - NULL, NULL, NULL); - if (isymbuf == NULL) - goto error_return; - } - - amt = symtab_hdr->sh_info; - amt *= sizeof (asection *); - sections = (asection **) bfd_malloc (amt); - if (sections == NULL && symtab_hdr->sh_info > 0) - goto error_return; - - isymend = isymbuf + symtab_hdr->sh_info; - for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) - { - asection *isec; - - if (isym->st_shndx == SHN_UNDEF) - isec = bfd_und_section_ptr; - else if (isym->st_shndx == SHN_ABS) - isec = bfd_abs_section_ptr; - else if (isym->st_shndx == SHN_COMMON) - isec = bfd_com_section_ptr; - else if (isym->st_shndx == SHN_M32R_SCOMMON) - isec = &m32r_elf_scom_section; - else - isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); - - *secpp = isec; - } - - if (! m32r_elf_relocate_section (output_bfd, link_info, input_bfd, - input_section, data, internal_relocs, - isymbuf, sections)) - goto error_return; - - if (sections != NULL) - free (sections); - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - free (isymbuf); - if (elf_section_data (input_section)->relocs != internal_relocs) - free (internal_relocs); - } - - return data; - - error_return: - if (sections != NULL) - free (sections); - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) - free (isymbuf); - if (internal_relocs != NULL - && elf_section_data (input_section)->relocs != internal_relocs) - free (internal_relocs); - return NULL; -} - -#endif /* #if 0 */ /* Set the right machine number. */ + static bfd_boolean -m32r_elf_object_p (abfd) - bfd *abfd; +m32r_elf_object_p (bfd *abfd) { switch (elf_elfheader (abfd)->e_flags & EF_M32R_ARCH) { @@ -4117,10 +3401,10 @@ m32r_elf_object_p (abfd) } /* Store the machine number in the flags field. */ + static void -m32r_elf_final_write_processing (abfd, linker) - bfd *abfd; - bfd_boolean linker ATTRIBUTE_UNUSED; +m32r_elf_final_write_processing (bfd *abfd, + bfd_boolean linker ATTRIBUTE_UNUSED) { unsigned long val; @@ -4137,10 +3421,9 @@ m32r_elf_final_write_processing (abfd, linker) } /* Function to keep M32R specific file flags. */ + static bfd_boolean -m32r_elf_set_private_flags (abfd, flags) - bfd *abfd; - flagword flags; +m32r_elf_set_private_flags (bfd *abfd, flagword flags) { BFD_ASSERT (!elf_flags_init (abfd) || elf_elfheader (abfd)->e_flags == flags); @@ -4152,11 +3435,11 @@ m32r_elf_set_private_flags (abfd, flags) /* Merge backend specific data from an object file to the output object file when linking. */ + static bfd_boolean -m32r_elf_merge_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; +m32r_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { + bfd *obfd = info->output_bfd; flagword out_flags; flagword in_flags; @@ -4183,9 +3466,8 @@ m32r_elf_merge_private_bfd_data (ibfd, obfd) if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) && bfd_get_arch_info (obfd)->the_default) - { - return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); - } + return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), + bfd_get_mach (ibfd)); return TRUE; } @@ -4200,9 +3482,8 @@ m32r_elf_merge_private_bfd_data (ibfd, obfd) || ((out_flags & EF_M32R_ARCH) == E_M32R_ARCH) || ((in_flags & EF_M32R_ARCH) == E_M32R2_ARCH)) { - (*_bfd_error_handler) - (_("%s: Instruction set mismatch with previous modules"), - bfd_archive_filename (ibfd)); + _bfd_error_handler + (_("%B: Instruction set mismatch with previous modules"), ibfd); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -4212,15 +3493,14 @@ m32r_elf_merge_private_bfd_data (ibfd, obfd) return TRUE; } -/* Display the flags field */ +/* Display the flags field. */ + static bfd_boolean -m32r_elf_print_private_bfd_data (abfd, ptr) - bfd *abfd; - PTR ptr; +m32r_elf_print_private_bfd_data (bfd *abfd, void * ptr) { FILE * file = (FILE *) ptr; - BFD_ASSERT (abfd != NULL && ptr != NULL) + BFD_ASSERT (abfd != NULL && ptr != NULL); _bfd_elf_print_private_bfd_data (abfd, ptr); @@ -4239,59 +3519,40 @@ m32r_elf_print_private_bfd_data (abfd, ptr) return TRUE; } -asection * -m32r_elf_gc_mark_hook (sec, info, rel, h, sym) - asection *sec; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - Elf_Internal_Rela *rel; - struct elf_link_hash_entry *h; - Elf_Internal_Sym *sym; +static asection * +m32r_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) + switch (ELF32_R_TYPE (rel->r_info)) { case R_M32R_GNU_VTINHERIT: case R_M32R_GNU_VTENTRY: case R_M32R_RELA_GNU_VTINHERIT: case R_M32R_RELA_GNU_VTENTRY: - break; - - default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; - - case bfd_link_hash_common: - return h->root.u.c.p->section; - - default: - break; - } - } - } - else - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); + return NULL; + } - return NULL; + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } static bfd_boolean -m32r_elf_gc_sweep_hook (abfd, info, sec, relocs) - bfd *abfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; +m32r_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) { /* Update the got entry reference counts for the section being removed. */ 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; + + if (bfd_link_relocatable (info)) + return TRUE; elf_section_data (sec)->local_dynrel = NULL; @@ -4301,80 +3562,95 @@ m32r_elf_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_M32R_GOT16_HI_ULO: - case R_M32R_GOT16_HI_SLO: - case R_M32R_GOT16_LO: - case R_M32R_GOT24: - case R_M32R_GOTPC_HI_ULO: - case R_M32R_GOTPC_HI_SLO: - case R_M32R_GOTPC_LO: - case R_M32R_GOTPC24: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount--; - } - else - { - if (local_got_refcounts && local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx]--; - } - break; + { + unsigned long r_symndx; + struct elf_link_hash_entry *h = NULL; - case R_M32R_16_RELA: - case R_M32R_24_RELA: - case R_M32R_32_RELA: - case R_M32R_HI16_ULO_RELA: - case R_M32R_HI16_SLO_RELA: - case R_M32R_LO16_RELA: - case R_M32R_SDA16_RELA: - case R_M32R_18_PCREL_RELA: - case R_M32R_26_PCREL_RELA: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf_m32r_link_hash_entry *eh; - struct elf_m32r_dyn_relocs **pp; - struct elf_m32r_dyn_relocs *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - - if (!info->shared && h->plt.refcount > 0) - h->plt.refcount -= 1; - - eh = (struct elf_m32r_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA - || ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_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; + } - case R_M32R_26_PLTREL: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount--; - } - break; - - default: - break; - } + switch (ELF32_R_TYPE (rel->r_info)) + { + 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: + case R_M32R_GOTPC_LO: + case R_M32R_GOTPC24: + if (h != NULL) + { + if (h->got.refcount > 0) + h->got.refcount--; + } + else + { + if (local_got_refcounts && local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx]--; + } + break; + + case R_M32R_16_RELA: + case R_M32R_24_RELA: + case R_M32R_32_RELA: + case R_M32R_REL32: + case R_M32R_HI16_ULO_RELA: + case R_M32R_HI16_SLO_RELA: + case R_M32R_LO16_RELA: + case R_M32R_SDA16_RELA: + case R_M32R_10_PCREL_RELA: + case R_M32R_18_PCREL_RELA: + case R_M32R_26_PCREL_RELA: + if (h != NULL) + { + struct elf_m32r_link_hash_entry *eh; + struct elf_m32r_dyn_relocs **pp; + struct elf_m32r_dyn_relocs *p; + + if (!bfd_link_pic (info) && h->plt.refcount > 0) + h->plt.refcount -= 1; + + eh = (struct elf_m32r_link_hash_entry *) h; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + if ( ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_10_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_REL32) + p->pc_count -= 1; + p->count -= 1; + if (p->count == 0) + *pp = p->next; + break; + } + } + break; + + case R_M32R_26_PLTREL: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount--; + } + break; + + default: + break; + } + } return TRUE; } @@ -4384,35 +3660,31 @@ m32r_elf_gc_sweep_hook (abfd, info, sec, relocs) virtual table relocs for gc. */ static bfd_boolean -m32r_elf_check_relocs (abfd, info, sec, relocs) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - const Elf_Internal_Rela *relocs; +m32r_elf_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; struct elf_m32r_link_hash_table *htab; bfd *dynobj; - bfd_vma *local_got_offsets; - asection *sgot, *srelgot, *sreloc; + asection *sreloc; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; - sgot = srelgot = sreloc = NULL; - + sreloc = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); - sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); - if (!elf_bad_symtab (abfd)) - sym_hashes_end -= symtab_hdr->sh_info; htab = m32r_elf_hash_table (info); + if (htab == NULL) + return FALSE; + dynobj = htab->root.dynobj; - local_got_offsets = elf_local_got_offsets (abfd); rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -4426,15 +3698,28 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) if (r_symndx < symtab_hdr->sh_info) h = NULL; else - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + { + h = sym_hashes[r_symndx - symtab_hdr->sh_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; + } /* Some relocs require a global offset table. */ - if (htab->sgot == NULL) + if (htab->root.sgot == NULL) { switch (r_type) { 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: @@ -4443,7 +3728,7 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) case R_M32R_GOT24: if (dynobj == NULL) htab->root.dynobj = dynobj = abfd; - if (! create_got_section (dynobj, info)) + if (!_bfd_elf_create_got_section (dynobj, info)) return FALSE; break; @@ -4474,8 +3759,7 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); - local_got_refcounts = ((bfd_signed_vma *) - bfd_zalloc (abfd, size)); + local_got_refcounts = bfd_zalloc (abfd, size); if (local_got_refcounts == NULL) return FALSE; elf_local_got_refcounts (abfd) = local_got_refcounts; @@ -4496,26 +3780,28 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) if (h == NULL) continue; - if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) + if (h->forced_local) break; - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->needs_plt = 1; h->plt.refcount += 1; break; case R_M32R_16_RELA: case R_M32R_24_RELA: case R_M32R_32_RELA: + case R_M32R_REL32: case R_M32R_HI16_ULO_RELA: case R_M32R_HI16_SLO_RELA: case R_M32R_LO16_RELA: case R_M32R_SDA16_RELA: + case R_M32R_10_PCREL_RELA: case R_M32R_18_PCREL_RELA: case R_M32R_26_PCREL_RELA: - if (h != NULL && !info->shared) + if (h != NULL && !bfd_link_pic (info)) { - h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + h->non_got_ref = 1; h->plt.refcount += 1; } @@ -4538,21 +3824,21 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the symbol. */ - if ((info->shared + if ((bfd_link_pic (info) && (sec->flags & SEC_ALLOC) != 0 - && ((r_type != R_M32R_26_PCREL_RELA - && r_type != R_M32R_18_PCREL_RELA) + && (( r_type != R_M32R_26_PCREL_RELA + && r_type != R_M32R_18_PCREL_RELA + && r_type != R_M32R_10_PCREL_RELA + && r_type != R_M32R_REL32) || (h != NULL && (! info->symbolic || h->root.type == bfd_link_hash_defweak - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)))) - || (!info->shared + || !h->def_regular)))) + || (!bfd_link_pic (info) && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (h->root.type == bfd_link_hash_defweak - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0))) + || !h->def_regular))) { struct elf_m32r_dyn_relocs *p; struct elf_m32r_dyn_relocs **head; @@ -4565,35 +3851,11 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) section in dynobj and make room for the reloc. */ if (sreloc == NULL) { - const char *name; - - name = (bfd_elf_string_from_elf_section - (abfd, - elf_elfheader (abfd)->e_shstrndx, - elf_section_data (sec)->rel_hdr.sh_name)); - if (name == NULL) - return FALSE; - - BFD_ASSERT (strncmp (name, ".rela", 5) == 0 - && strcmp (bfd_get_section_name (abfd, sec), - name + 5) == 0); + sreloc = _bfd_elf_make_dynamic_reloc_section + (sec, dynobj, 2, abfd, /*rela?*/ TRUE); - sreloc = bfd_get_section_by_name (dynobj, name); - if (sreloc == NULL) - { - flagword flags; - - sreloc = bfd_make_section (dynobj, name); - flags = (SEC_HAS_CONTENTS | SEC_READONLY - | SEC_IN_MEMORY | SEC_LINKER_CREATED); - if ((sec->flags & SEC_ALLOC) != 0) - flags |= SEC_ALLOC | SEC_LOAD; - if (sreloc == NULL - || ! bfd_set_section_flags (dynobj, sreloc, flags) - || ! bfd_set_section_alignment (dynobj, sreloc, 2)) - return FALSE; - } - elf_section_data (sec)->sreloc = sreloc; + if (sreloc == NULL) + return FALSE; } /* If this is a global symbol, we count the number of @@ -4602,23 +3864,30 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) head = &((struct elf_m32r_link_hash_entry *) h)->dyn_relocs; else { + /* Track dynamic relocs needed for local syms too. */ asection *s; + void *vpp; + Elf_Internal_Sym *isym; - /* Track dynamic relocs needed for local syms too. */ - s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, - sec, r_symndx); - if (s == NULL) - return FALSE; + isym = bfd_sym_from_r_symndx (&htab->sym_cache, + abfd, r_symndx); + if (isym == NULL) + return FALSE; - head = ((struct elf_m32r_dyn_relocs **) - &elf_section_data (s)->local_dynrel); + s = bfd_section_from_elf_index (abfd, isym->st_shndx); + if (s == NULL) + s = sec; + + vpp = &elf_section_data (s)->local_dynrel; + head = (struct elf_m32r_dyn_relocs **) vpp; } p = *head; if (p == NULL || p->sec != sec) { bfd_size_type amt = sizeof (*p); - p = ((struct elf_m32r_dyn_relocs *) bfd_alloc (dynobj, amt)); + + p = bfd_alloc (dynobj, amt); if (p == NULL) return FALSE; p->next = *head; @@ -4629,8 +3898,10 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) } p->count += 1; - if (ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA - || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA) + if ( ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_10_PCREL_RELA + || ELF32_R_TYPE (rel->r_info) == R_M32R_REL32) p->pc_count += 1; } break; @@ -4646,11 +3917,15 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_M32R_GNU_VTENTRY: - if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) return FALSE; break; case R_M32R_RELA_GNU_VTENTRY: - if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; } @@ -4659,76 +3934,36 @@ m32r_elf_check_relocs (abfd, info, sec, relocs) return TRUE; } -static struct bfd_elf_special_section const m32r_elf_special_sections[]= +static const struct bfd_elf_special_section m32r_elf_special_sections[] = { - { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, - { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, - { NULL, 0, 0, 0, 0 } + { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, + { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, + { NULL, 0, 0, 0, 0 } }; -static bfd_boolean -m32r_elf_fake_sections (abfd, hdr, sec) - bfd *abfd; - Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED; - asection *sec; -{ - register const char *name; - - name = bfd_get_section_name (abfd, sec); - - /* The generic elf_fake_sections will set up REL_HDR using the - default kind of relocations. But, we may actually need both - kinds of relocations, so we set up the second header here. - - This is not necessary for the O32 ABI since that only uses Elf32_Rel - relocations (cf. System V ABI, MIPS RISC Processor Supplement, - 3rd Edition, p. 4-17). It breaks the IRIX 5/6 32-bit ld, since one - of the resulting empty .rela.
sections starts with - sh_offset == object size, and ld doesn't allow that. While the check - is arguably bogus for empty or SHT_NOBITS sections, it can easily be - avoided by not emitting those useless sections in the first place. */ - if ((sec->flags & SEC_RELOC) != 0) - { - struct bfd_elf_section_data *esd; - bfd_size_type amt = sizeof (Elf_Internal_Shdr); - - esd = elf_section_data (sec); - BFD_ASSERT (esd->rel_hdr2 == NULL); - esd->rel_hdr2 = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt); - if (!esd->rel_hdr2) - return FALSE; - _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, - !sec->use_rela_p); - } - - return TRUE; -} - static enum elf_reloc_type_class -m32r_elf_reloc_type_class (rela) - const Elf_Internal_Rela *rela; +m32r_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela) { switch ((int) ELF32_R_TYPE (rela->r_info)) { - case R_M32R_RELATIVE: - return reloc_class_relative; - case R_M32R_JMP_SLOT: - return reloc_class_plt; - case R_M32R_COPY: - return reloc_class_copy; - default: - return reloc_class_normal; + case R_M32R_RELATIVE: return reloc_class_relative; + case R_M32R_JMP_SLOT: return reloc_class_plt; + case R_M32R_COPY: return reloc_class_copy; + default: return reloc_class_normal; } } #define ELF_ARCH bfd_arch_m32r +#define ELF_TARGET_ID M32R_ELF_DATA #define ELF_MACHINE_CODE EM_M32R #define ELF_MACHINE_ALT1 EM_CYGNUS_M32R #define ELF_MAXPAGESIZE 0x1 /* Explicitly requested by Mitsubishi. */ -#define TARGET_BIG_SYM bfd_elf32_m32r_vec +#define TARGET_BIG_SYM m32r_elf32_vec #define TARGET_BIG_NAME "elf32-m32r" -#define TARGET_LITTLE_SYM bfd_elf32_m32rle_vec +#define TARGET_LITTLE_SYM m32r_elf32_le_vec #define TARGET_LITTLE_NAME "elf32-m32rle" #define elf_info_to_howto m32r_info_to_howto @@ -4744,6 +3979,8 @@ m32r_elf_reloc_type_class (rela) #define elf_backend_create_dynamic_sections m32r_elf_create_dynamic_sections #define bfd_elf32_bfd_link_hash_table_create m32r_elf_link_hash_table_create #define elf_backend_size_dynamic_sections m32r_elf_size_dynamic_sections +#define elf_backend_omit_section_dynsym \ + ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_finish_dynamic_sections m32r_elf_finish_dynamic_sections #define elf_backend_adjust_dynamic_symbol m32r_elf_adjust_dynamic_symbol #define elf_backend_finish_dynamic_symbol m32r_elf_finish_dynamic_symbol @@ -4759,6 +3996,7 @@ m32r_elf_reloc_type_class (rela) #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 #define elf_backend_got_header_size 12 +#define elf_backend_dtrel_excludes_plt 1 #define elf_backend_may_use_rel_p 1 #ifdef USE_M32R_OLD_RELOC @@ -4767,14 +4005,6 @@ m32r_elf_reloc_type_class (rela) #else #define elf_backend_default_use_rela_p 1 #define elf_backend_may_use_rela_p 1 -#define elf_backend_fake_sections m32r_elf_fake_sections -#endif - -#if 0 /* not yet */ -/* relax support */ -#define bfd_elf32_bfd_relax_section m32r_elf_relax_section -#define bfd_elf32_bfd_get_relocated_section_contents \ - m32r_elf_get_relocated_section_contents #endif #define elf_backend_object_p m32r_elf_object_p @@ -4786,19 +4016,18 @@ m32r_elf_reloc_type_class (rela) #include "elf32-target.h" -#undef ELF_MAXPAGESIZE +#undef ELF_MAXPAGESIZE #define ELF_MAXPAGESIZE 0x1000 -#undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_m32rlin_vec -#undef TARGET_BIG_NAME +#undef TARGET_BIG_SYM +#define TARGET_BIG_SYM m32r_elf32_linux_vec +#undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-m32r-linux" -#undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_m32rlelin_vec -#undef TARGET_LITTLE_NAME +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM m32r_elf32_linux_le_vec +#undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-m32rle-linux" -#undef elf32_bed +#undef elf32_bed #define elf32_bed elf32_m32r_lin_bed #include "elf32-target.h" -