xref: /openbsd-src/gnu/usr.bin/binutils/bfd/elf32-arc.c (revision d2201f2f89f0be1a0be6f7568000ed297414a06d)
1f7cc78ecSespie /* ARC-specific support for 32-bit ELF
2*d2201f2fSdrahn    Copyright 1994, 1995, 1997, 1999, 2001, 2002
3*d2201f2fSdrahn    Free Software Foundation, Inc.
4f7cc78ecSespie    Contributed by Doug Evans (dje@cygnus.com).
5f7cc78ecSespie 
6f7cc78ecSespie    This file is part of BFD, the Binary File Descriptor library.
7f7cc78ecSespie 
8f7cc78ecSespie    This program is free software; you can redistribute it and/or modify
9f7cc78ecSespie    it under the terms of the GNU General Public License as published by
10f7cc78ecSespie    the Free Software Foundation; either version 2 of the License, or
11f7cc78ecSespie    (at your option) any later version.
12f7cc78ecSespie 
13f7cc78ecSespie    This program is distributed in the hope that it will be useful,
14f7cc78ecSespie    but WITHOUT ANY WARRANTY; without even the implied warranty of
15f7cc78ecSespie    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f7cc78ecSespie    GNU General Public License for more details.
17f7cc78ecSespie 
18f7cc78ecSespie    You should have received a copy of the GNU General Public License
19f7cc78ecSespie    along with this program; if not, write to the Free Software
20f7cc78ecSespie    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21f7cc78ecSespie 
22f7cc78ecSespie #include "bfd.h"
23f7cc78ecSespie #include "sysdep.h"
24f7cc78ecSespie #include "libbfd.h"
25f7cc78ecSespie #include "elf-bfd.h"
26f7cc78ecSespie #include "elf/arc.h"
27*d2201f2fSdrahn #include "libiberty.h"
28f7cc78ecSespie 
29f7cc78ecSespie static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
30f7cc78ecSespie   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
31f7cc78ecSespie static void arc_info_to_howto_rel
32*d2201f2fSdrahn   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
33*d2201f2fSdrahn static bfd_boolean arc_elf_object_p
345f210c2aSfgsch   PARAMS ((bfd *));
355f210c2aSfgsch static void arc_elf_final_write_processing
36*d2201f2fSdrahn   PARAMS ((bfd *, bfd_boolean));
37*d2201f2fSdrahn static bfd_reloc_status_type arc_elf_b22_pcrel
38*d2201f2fSdrahn   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
39f7cc78ecSespie 
40f7cc78ecSespie /* Try to minimize the amount of space occupied by relocation tables
41f7cc78ecSespie    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
425f210c2aSfgsch 
43*d2201f2fSdrahn #define USE_REL	1
44f7cc78ecSespie 
45f7cc78ecSespie static reloc_howto_type elf_arc_howto_table[] =
46f7cc78ecSespie {
47f7cc78ecSespie   /* This reloc does nothing.  */
48f7cc78ecSespie   HOWTO (R_ARC_NONE,		/* type  */
49f7cc78ecSespie 	 0,			/* rightshift  */
50f7cc78ecSespie 	 2,			/* size (0 = byte, 1 = short, 2 = long)  */
51f7cc78ecSespie 	 32,			/* bitsize  */
52*d2201f2fSdrahn 	 FALSE,			/* pc_relative  */
53f7cc78ecSespie 	 0,			/* bitpos  */
54f7cc78ecSespie 	 complain_overflow_bitfield, /* complain_on_overflow  */
55f7cc78ecSespie 	 bfd_elf_generic_reloc,	/* special_function  */
56f7cc78ecSespie 	 "R_ARC_NONE",		/* name  */
57*d2201f2fSdrahn 	 TRUE,			/* partial_inplace  */
58f7cc78ecSespie 	 0,			/* src_mask  */
59f7cc78ecSespie 	 0,			/* dst_mask  */
60*d2201f2fSdrahn 	 FALSE),		/* pcrel_offset  */
61f7cc78ecSespie 
62f7cc78ecSespie   /* A standard 32 bit relocation.  */
63f7cc78ecSespie   HOWTO (R_ARC_32,		/* type  */
64f7cc78ecSespie 	 0,			/* rightshift  */
65f7cc78ecSespie 	 2,			/* size (0 = byte, 1 = short, 2 = long)  */
66f7cc78ecSespie 	 32,			/* bitsize  */
67*d2201f2fSdrahn 	 FALSE,			/* pc_relative  */
68f7cc78ecSespie 	 0,			/* bitpos  */
69f7cc78ecSespie 	 complain_overflow_bitfield, /* complain_on_overflow  */
70f7cc78ecSespie 	 bfd_elf_generic_reloc,	/* special_function  */
71f7cc78ecSespie 	 "R_ARC_32",		/* name  */
72*d2201f2fSdrahn 	 TRUE,			/* partial_inplace  */
73f7cc78ecSespie 	 0xffffffff,		/* src_mask  */
74f7cc78ecSespie 	 0xffffffff,		/* dst_mask  */
75*d2201f2fSdrahn 	 FALSE),		/* pcrel_offset  */
76f7cc78ecSespie 
77f7cc78ecSespie   /* A 26 bit absolute branch, right shifted by 2.  */
78f7cc78ecSespie   HOWTO (R_ARC_B26,		/* type  */
79f7cc78ecSespie 	 2,			/* rightshift  */
80f7cc78ecSespie 	 2,			/* size (0 = byte, 1 = short, 2 = long)  */
81f7cc78ecSespie 	 26,			/* bitsize  */
82*d2201f2fSdrahn 	 FALSE,			/* pc_relative  */
83f7cc78ecSespie 	 0,			/* bitpos  */
84f7cc78ecSespie 	 complain_overflow_bitfield, /* complain_on_overflow  */
85f7cc78ecSespie 	 bfd_elf_generic_reloc,	/* special_function  */
86f7cc78ecSespie 	 "R_ARC_B26",		/* name  */
87*d2201f2fSdrahn 	 TRUE,			/* partial_inplace  */
88f7cc78ecSespie 	 0x00ffffff,		/* src_mask  */
89f7cc78ecSespie 	 0x00ffffff,		/* dst_mask  */
90*d2201f2fSdrahn 	 FALSE),		/* pcrel_offset  */
91f7cc78ecSespie 
92f7cc78ecSespie   /* A relative 22 bit branch; bits 21-2 are stored in bits 26-7.  */
93f7cc78ecSespie   HOWTO (R_ARC_B22_PCREL,	/* type  */
94f7cc78ecSespie 	 2,			/* rightshift  */
95f7cc78ecSespie 	 2,			/* size (0 = byte, 1 = short, 2 = long)  */
96f7cc78ecSespie 	 22,			/* bitsize  */
97*d2201f2fSdrahn 	 TRUE,			/* pc_relative  */
98f7cc78ecSespie 	 7,			/* bitpos  */
99f7cc78ecSespie 	 complain_overflow_signed, /* complain_on_overflow  */
100*d2201f2fSdrahn 	 arc_elf_b22_pcrel,	/* special_function  */
101f7cc78ecSespie 	 "R_ARC_B22_PCREL",	/* name  */
102*d2201f2fSdrahn 	 TRUE,			/* partial_inplace  */
103f7cc78ecSespie 	 0x07ffff80,		/* src_mask  */
104f7cc78ecSespie 	 0x07ffff80,		/* dst_mask  */
105*d2201f2fSdrahn 	 FALSE),		/* pcrel_offset  */
106f7cc78ecSespie };
107f7cc78ecSespie 
108f7cc78ecSespie /* Map BFD reloc types to ARC ELF reloc types.  */
109f7cc78ecSespie 
110f7cc78ecSespie struct arc_reloc_map
111f7cc78ecSespie {
112f7cc78ecSespie   bfd_reloc_code_real_type bfd_reloc_val;
113f7cc78ecSespie   unsigned char elf_reloc_val;
114f7cc78ecSespie };
115f7cc78ecSespie 
116f7cc78ecSespie static const struct arc_reloc_map arc_reloc_map[] =
117f7cc78ecSespie {
118f7cc78ecSespie   { BFD_RELOC_NONE, R_ARC_NONE, },
119f7cc78ecSespie   { BFD_RELOC_32, R_ARC_32 },
120f7cc78ecSespie   { BFD_RELOC_CTOR, R_ARC_32 },
121f7cc78ecSespie   { BFD_RELOC_ARC_B26, R_ARC_B26 },
122f7cc78ecSespie   { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL },
123f7cc78ecSespie };
124f7cc78ecSespie 
125f7cc78ecSespie static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup(abfd,code)126f7cc78ecSespie bfd_elf32_bfd_reloc_type_lookup (abfd, code)
127f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
128f7cc78ecSespie      bfd_reloc_code_real_type code;
129f7cc78ecSespie {
130f7cc78ecSespie   unsigned int i;
131f7cc78ecSespie 
132*d2201f2fSdrahn   for (i = ARRAY_SIZE (arc_reloc_map); i--;)
133f7cc78ecSespie     if (arc_reloc_map[i].bfd_reloc_val == code)
134*d2201f2fSdrahn       return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
135*d2201f2fSdrahn 
136f7cc78ecSespie   return NULL;
137f7cc78ecSespie }
138f7cc78ecSespie 
139f7cc78ecSespie /* Set the howto pointer for an ARC ELF reloc.  */
140f7cc78ecSespie 
141f7cc78ecSespie static void
arc_info_to_howto_rel(abfd,cache_ptr,dst)142f7cc78ecSespie arc_info_to_howto_rel (abfd, cache_ptr, dst)
143f7cc78ecSespie      bfd *abfd ATTRIBUTE_UNUSED;
144f7cc78ecSespie      arelent *cache_ptr;
145*d2201f2fSdrahn      Elf_Internal_Rela *dst;
146f7cc78ecSespie {
147f7cc78ecSespie   unsigned int r_type;
148f7cc78ecSespie 
149f7cc78ecSespie   r_type = ELF32_R_TYPE (dst->r_info);
150f7cc78ecSespie   BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
151f7cc78ecSespie   cache_ptr->howto = &elf_arc_howto_table[r_type];
152f7cc78ecSespie }
153f7cc78ecSespie 
154f7cc78ecSespie /* Set the right machine number for an ARC ELF file.  */
155f7cc78ecSespie 
156*d2201f2fSdrahn static bfd_boolean
arc_elf_object_p(abfd)157f7cc78ecSespie arc_elf_object_p (abfd)
158f7cc78ecSespie      bfd *abfd;
159f7cc78ecSespie {
160*d2201f2fSdrahn   unsigned int mach = bfd_mach_arc_6;
1615f210c2aSfgsch 
1625f210c2aSfgsch   if (elf_elfheader(abfd)->e_machine == EM_ARC)
1635f210c2aSfgsch     {
164f7cc78ecSespie       unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH;
165f7cc78ecSespie 
166f7cc78ecSespie       switch (arch)
167f7cc78ecSespie 	{
1685f210c2aSfgsch 	case E_ARC_MACH_ARC5:
1695f210c2aSfgsch 	  mach = bfd_mach_arc_5;
170f7cc78ecSespie 	  break;
171f7cc78ecSespie 	default:
1725f210c2aSfgsch 	case E_ARC_MACH_ARC6:
1735f210c2aSfgsch 	  mach = bfd_mach_arc_6;
1745f210c2aSfgsch 	  break;
1755f210c2aSfgsch 	case E_ARC_MACH_ARC7:
1765f210c2aSfgsch 	  mach = bfd_mach_arc_7;
1775f210c2aSfgsch 	  break;
1785f210c2aSfgsch 	case E_ARC_MACH_ARC8:
1795f210c2aSfgsch 	  mach = bfd_mach_arc_8;
1805f210c2aSfgsch 	  break;
181f7cc78ecSespie 	}
1825f210c2aSfgsch     }
1835f210c2aSfgsch   return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
184f7cc78ecSespie }
185f7cc78ecSespie 
186f7cc78ecSespie /* The final processing done just before writing out an ARC ELF object file.
187f7cc78ecSespie    This gets the ARC architecture right based on the machine number.  */
188f7cc78ecSespie 
189f7cc78ecSespie static void
arc_elf_final_write_processing(abfd,linker)190f7cc78ecSespie arc_elf_final_write_processing (abfd, linker)
191f7cc78ecSespie      bfd *abfd;
192*d2201f2fSdrahn      bfd_boolean linker ATTRIBUTE_UNUSED;
193f7cc78ecSespie {
194f7cc78ecSespie   unsigned long val;
195f7cc78ecSespie 
1965f210c2aSfgsch   switch (bfd_get_mach (abfd))
197f7cc78ecSespie     {
1985f210c2aSfgsch     case bfd_mach_arc_5:
1995f210c2aSfgsch       val = E_ARC_MACH_ARC5;
200f7cc78ecSespie       break;
201f7cc78ecSespie     default:
2025f210c2aSfgsch     case bfd_mach_arc_6:
2035f210c2aSfgsch       val = E_ARC_MACH_ARC6;
2045f210c2aSfgsch       break;
2055f210c2aSfgsch     case bfd_mach_arc_7:
2065f210c2aSfgsch       val = E_ARC_MACH_ARC7;
2075f210c2aSfgsch       break;
2085f210c2aSfgsch     case bfd_mach_arc_8:
2095f210c2aSfgsch       val = E_ARC_MACH_ARC8;
2105f210c2aSfgsch       break;
211f7cc78ecSespie     }
212f7cc78ecSespie   elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH;
213f7cc78ecSespie   elf_elfheader (abfd)->e_flags |= val;
214f7cc78ecSespie }
215f7cc78ecSespie 
216*d2201f2fSdrahn bfd_reloc_status_type
arc_elf_b22_pcrel(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)217*d2201f2fSdrahn arc_elf_b22_pcrel (abfd, reloc_entry, symbol, data, input_section,
218*d2201f2fSdrahn 		   output_bfd, error_message)
219*d2201f2fSdrahn      bfd * abfd;
220*d2201f2fSdrahn      arelent * reloc_entry;
221*d2201f2fSdrahn      asymbol * symbol;
222*d2201f2fSdrahn      PTR data;
223*d2201f2fSdrahn      asection * input_section;
224*d2201f2fSdrahn      bfd * output_bfd;
225*d2201f2fSdrahn      char ** error_message;
226*d2201f2fSdrahn {
227*d2201f2fSdrahn   /* If linking, back up the final symbol address by the address of the
228*d2201f2fSdrahn      reloc.  This cannot be accomplished by setting the pcrel_offset
229*d2201f2fSdrahn      field to TRUE, as bfd_install_relocation will detect this and refuse
230*d2201f2fSdrahn      to install the offset in the first place, but bfd_perform_relocation
231*d2201f2fSdrahn      will still insist on removing it.  */
232*d2201f2fSdrahn   if (output_bfd == (bfd *) NULL)
233*d2201f2fSdrahn     reloc_entry->addend -= reloc_entry->address;
234*d2201f2fSdrahn 
235*d2201f2fSdrahn   /* Fall through to the default elf reloc handler.  */
236*d2201f2fSdrahn   return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
237*d2201f2fSdrahn 				input_section, output_bfd, error_message);
238*d2201f2fSdrahn }
239*d2201f2fSdrahn 
240f7cc78ecSespie #define TARGET_LITTLE_SYM bfd_elf32_littlearc_vec
241f7cc78ecSespie #define TARGET_LITTLE_NAME "elf32-littlearc"
242f7cc78ecSespie #define TARGET_BIG_SYM bfd_elf32_bigarc_vec
243f7cc78ecSespie #define TARGET_BIG_NAME	"elf32-bigarc"
244f7cc78ecSespie #define ELF_ARCH bfd_arch_arc
2455f210c2aSfgsch #define ELF_MACHINE_CODE EM_ARC
246f7cc78ecSespie #define ELF_MAXPAGESIZE	0x1000
247f7cc78ecSespie 
248f7cc78ecSespie #define elf_info_to_howto 0
249f7cc78ecSespie #define elf_info_to_howto_rel arc_info_to_howto_rel
250f7cc78ecSespie #define elf_backend_object_p arc_elf_object_p
2515f210c2aSfgsch #define elf_backend_final_write_processing arc_elf_final_write_processing
252f7cc78ecSespie 
253f7cc78ecSespie #include "elf32-target.h"
254