138889Sjdp/* ARC-specific support for 32-bit ELF 2218822Sdim Copyright 1994, 1995, 1997, 1999, 2001, 2002, 2005, 2007 3130561Sobrien Free Software Foundation, Inc. 438889Sjdp Contributed by Doug Evans (dje@cygnus.com). 538889Sjdp 685815Sobrien This file is part of BFD, the Binary File Descriptor library. 738889Sjdp 885815Sobrien This program is free software; you can redistribute it and/or modify 985815Sobrien it under the terms of the GNU General Public License as published by 1085815Sobrien the Free Software Foundation; either version 2 of the License, or 1185815Sobrien (at your option) any later version. 1238889Sjdp 1385815Sobrien This program is distributed in the hope that it will be useful, 1485815Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1585815Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1685815Sobrien GNU General Public License for more details. 1738889Sjdp 1885815Sobrien You should have received a copy of the GNU General Public License 1985815Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21218822Sdim MA 02110-1301, USA. */ 2238889Sjdp 23218822Sdim#include "sysdep.h" 2438889Sjdp#include "bfd.h" 2538889Sjdp#include "libbfd.h" 2638889Sjdp#include "elf-bfd.h" 2738889Sjdp#include "elf/arc.h" 2889857Sobrien#include "libiberty.h" 2938889Sjdp 3038889Sjdp/* Try to minimize the amount of space occupied by relocation tables 3138889Sjdp on the ROM (not that the ROM won't be swamped by other ELF overhead). */ 3285815Sobrien 33130561Sobrien#define USE_REL 1 3438889Sjdp 35218822Sdimstatic bfd_reloc_status_type 36218822Sdimarc_elf_b22_pcrel (bfd * abfd, 37218822Sdim arelent * reloc_entry, 38218822Sdim asymbol * symbol, 39218822Sdim void * data, 40218822Sdim asection * input_section, 41218822Sdim bfd * output_bfd, 42218822Sdim char ** error_message) 43218822Sdim{ 44218822Sdim /* If linking, back up the final symbol address by the address of the 45218822Sdim reloc. This cannot be accomplished by setting the pcrel_offset 46218822Sdim field to TRUE, as bfd_install_relocation will detect this and refuse 47218822Sdim to install the offset in the first place, but bfd_perform_relocation 48218822Sdim will still insist on removing it. */ 49218822Sdim if (output_bfd == NULL) 50218822Sdim reloc_entry->addend -= reloc_entry->address; 51218822Sdim 52218822Sdim /* Fall through to the default elf reloc handler. */ 53218822Sdim return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 54218822Sdim input_section, output_bfd, error_message); 55218822Sdim} 56218822Sdim 5738889Sjdpstatic reloc_howto_type elf_arc_howto_table[] = 5838889Sjdp{ 5938889Sjdp /* This reloc does nothing. */ 60218822Sdim HOWTO (R_ARC_NONE, /* Type. */ 61218822Sdim 0, /* Rightshift. */ 62218822Sdim 2, /* Size (0 = byte, 1 = short, 2 = long). */ 63218822Sdim 32, /* Bitsize. */ 64218822Sdim FALSE, /* PC_relative. */ 65218822Sdim 0, /* Bitpos. */ 66218822Sdim complain_overflow_bitfield, /* Complain_on_overflow. */ 67218822Sdim bfd_elf_generic_reloc, /* Special_function. */ 68218822Sdim "R_ARC_NONE", /* Name. */ 69218822Sdim TRUE, /* Partial_inplace. */ 70218822Sdim 0, /* Src_mask. */ 71218822Sdim 0, /* Dst_mask. */ 72218822Sdim FALSE), /* PCrel_offset. */ 7338889Sjdp 7438889Sjdp /* A standard 32 bit relocation. */ 75218822Sdim HOWTO (R_ARC_32, /* Type. */ 76218822Sdim 0, /* Rightshift. */ 77218822Sdim 2, /* Size (0 = byte, 1 = short, 2 = long). */ 78218822Sdim 32, /* Bitsize. */ 79218822Sdim FALSE, /* PC_relative. */ 80218822Sdim 0, /* Bitpos. */ 81218822Sdim complain_overflow_bitfield, /* Complain_on_overflow. */ 82218822Sdim bfd_elf_generic_reloc, /* Special_function. */ 83218822Sdim "R_ARC_32", /* Name. */ 84218822Sdim TRUE, /* Partial_inplace. */ 85218822Sdim 0xffffffff, /* Src_mask. */ 86218822Sdim 0xffffffff, /* Dst_mask. */ 87218822Sdim FALSE), /* PCrel_offset. */ 8838889Sjdp 8938889Sjdp /* A 26 bit absolute branch, right shifted by 2. */ 90218822Sdim HOWTO (R_ARC_B26, /* Type. */ 91218822Sdim 2, /* Rightshift. */ 92218822Sdim 2, /* Size (0 = byte, 1 = short, 2 = long). */ 93218822Sdim 26, /* Bitsize. */ 94218822Sdim FALSE, /* PC_relative. */ 95218822Sdim 0, /* Bitpos. */ 96218822Sdim complain_overflow_bitfield, /* Complain_on_overflow. */ 97218822Sdim bfd_elf_generic_reloc, /* Special_function. */ 98218822Sdim "R_ARC_B26", /* Name. */ 99218822Sdim TRUE, /* Partial_inplace. */ 100218822Sdim 0x00ffffff, /* Src_mask. */ 101218822Sdim 0x00ffffff, /* Dst_mask. */ 102218822Sdim FALSE), /* PCrel_offset. */ 10338889Sjdp 10438889Sjdp /* A relative 22 bit branch; bits 21-2 are stored in bits 26-7. */ 105218822Sdim HOWTO (R_ARC_B22_PCREL, /* Type. */ 106218822Sdim 2, /* Rightshift. */ 107218822Sdim 2, /* Size (0 = byte, 1 = short, 2 = long). */ 108218822Sdim 22, /* Bitsize. */ 109218822Sdim TRUE, /* PC_relative. */ 110218822Sdim 7, /* Bitpos. */ 111218822Sdim complain_overflow_signed, /* Complain_on_overflow. */ 112218822Sdim arc_elf_b22_pcrel, /* Special_function. */ 113218822Sdim "R_ARC_B22_PCREL", /* Name. */ 114218822Sdim TRUE, /* Partial_inplace. */ 115218822Sdim 0x07ffff80, /* Src_mask. */ 116218822Sdim 0x07ffff80, /* Dst_mask. */ 117218822Sdim FALSE), /* PCrel_offset. */ 11838889Sjdp}; 11938889Sjdp 12038889Sjdp/* Map BFD reloc types to ARC ELF reloc types. */ 12138889Sjdp 12238889Sjdpstruct arc_reloc_map 12338889Sjdp{ 12460484Sobrien bfd_reloc_code_real_type bfd_reloc_val; 12538889Sjdp unsigned char elf_reloc_val; 12638889Sjdp}; 12738889Sjdp 12838889Sjdpstatic const struct arc_reloc_map arc_reloc_map[] = 12938889Sjdp{ 13038889Sjdp { BFD_RELOC_NONE, R_ARC_NONE, }, 13138889Sjdp { BFD_RELOC_32, R_ARC_32 }, 13238889Sjdp { BFD_RELOC_CTOR, R_ARC_32 }, 13338889Sjdp { BFD_RELOC_ARC_B26, R_ARC_B26 }, 13438889Sjdp { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL }, 13538889Sjdp}; 13638889Sjdp 13738889Sjdpstatic reloc_howto_type * 138218822Sdimbfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 139218822Sdim bfd_reloc_code_real_type code) 14038889Sjdp{ 14138889Sjdp unsigned int i; 14238889Sjdp 14389857Sobrien for (i = ARRAY_SIZE (arc_reloc_map); i--;) 14489857Sobrien if (arc_reloc_map[i].bfd_reloc_val == code) 14589857Sobrien return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val; 14689857Sobrien 14738889Sjdp return NULL; 14838889Sjdp} 14938889Sjdp 150218822Sdimstatic reloc_howto_type * 151218822Sdimbfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 152218822Sdim const char *r_name) 153218822Sdim{ 154218822Sdim unsigned int i; 155218822Sdim 156218822Sdim for (i = 0; 157218822Sdim i < sizeof (elf_arc_howto_table) / sizeof (elf_arc_howto_table[0]); 158218822Sdim i++) 159218822Sdim if (elf_arc_howto_table[i].name != NULL 160218822Sdim && strcasecmp (elf_arc_howto_table[i].name, r_name) == 0) 161218822Sdim return &elf_arc_howto_table[i]; 162218822Sdim 163218822Sdim return NULL; 164218822Sdim} 165218822Sdim 16638889Sjdp/* Set the howto pointer for an ARC ELF reloc. */ 16738889Sjdp 16838889Sjdpstatic void 169218822Sdimarc_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, 170218822Sdim arelent *cache_ptr, 171218822Sdim Elf_Internal_Rela *dst) 17238889Sjdp{ 17338889Sjdp unsigned int r_type; 17438889Sjdp 17538889Sjdp r_type = ELF32_R_TYPE (dst->r_info); 17638889Sjdp BFD_ASSERT (r_type < (unsigned int) R_ARC_max); 17738889Sjdp cache_ptr->howto = &elf_arc_howto_table[r_type]; 17838889Sjdp} 17938889Sjdp 18038889Sjdp/* Set the right machine number for an ARC ELF file. */ 18138889Sjdp 182130561Sobrienstatic bfd_boolean 183218822Sdimarc_elf_object_p (bfd *abfd) 18438889Sjdp{ 18589857Sobrien unsigned int mach = bfd_mach_arc_6; 18638889Sjdp 18785815Sobrien if (elf_elfheader(abfd)->e_machine == EM_ARC) 18838889Sjdp { 18985815Sobrien unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH; 19085815Sobrien 19185815Sobrien switch (arch) 19285815Sobrien { 19385815Sobrien case E_ARC_MACH_ARC5: 19485815Sobrien mach = bfd_mach_arc_5; 19585815Sobrien break; 19685815Sobrien default: 19785815Sobrien case E_ARC_MACH_ARC6: 19885815Sobrien mach = bfd_mach_arc_6; 19985815Sobrien break; 20085815Sobrien case E_ARC_MACH_ARC7: 20185815Sobrien mach = bfd_mach_arc_7; 20285815Sobrien break; 20385815Sobrien case E_ARC_MACH_ARC8: 20485815Sobrien mach = bfd_mach_arc_8; 20585815Sobrien break; 20685815Sobrien } 20738889Sjdp } 20885815Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach); 20938889Sjdp} 21038889Sjdp 21138889Sjdp/* The final processing done just before writing out an ARC ELF object file. 21238889Sjdp This gets the ARC architecture right based on the machine number. */ 21338889Sjdp 21438889Sjdpstatic void 215218822Sdimarc_elf_final_write_processing (bfd *abfd, 216218822Sdim bfd_boolean linker ATTRIBUTE_UNUSED) 21738889Sjdp{ 21838889Sjdp unsigned long val; 21938889Sjdp 22085815Sobrien switch (bfd_get_mach (abfd)) 22138889Sjdp { 22285815Sobrien case bfd_mach_arc_5: 22385815Sobrien val = E_ARC_MACH_ARC5; 22438889Sjdp break; 22538889Sjdp default: 22685815Sobrien case bfd_mach_arc_6: 22785815Sobrien val = E_ARC_MACH_ARC6; 22885815Sobrien break; 22985815Sobrien case bfd_mach_arc_7: 23085815Sobrien val = E_ARC_MACH_ARC7; 23185815Sobrien break; 23285815Sobrien case bfd_mach_arc_8: 23385815Sobrien val = E_ARC_MACH_ARC8; 23485815Sobrien break; 23538889Sjdp } 23638889Sjdp elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH; 23738889Sjdp elf_elfheader (abfd)->e_flags |= val; 23838889Sjdp} 23938889Sjdp 240218822Sdim#define TARGET_LITTLE_SYM bfd_elf32_littlearc_vec 241218822Sdim#define TARGET_LITTLE_NAME "elf32-littlearc" 242218822Sdim#define TARGET_BIG_SYM bfd_elf32_bigarc_vec 243218822Sdim#define TARGET_BIG_NAME "elf32-bigarc" 244218822Sdim#define ELF_ARCH bfd_arch_arc 245218822Sdim#define ELF_MACHINE_CODE EM_ARC 246218822Sdim#define ELF_MAXPAGESIZE 0x1000 24789857Sobrien 248218822Sdim#define elf_info_to_howto 0 249218822Sdim#define elf_info_to_howto_rel arc_info_to_howto_rel 250218822Sdim#define elf_backend_object_p arc_elf_object_p 251218822Sdim#define elf_backend_final_write_processing arc_elf_final_write_processing 252104834Sobrien 25338889Sjdp#include "elf32-target.h" 254