This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / bfd / elf32-arc.c
1 /* ARC-specific support for 32-bit ELF
2    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3    Contributed by Doug Evans (dje@cygnus.com).
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "libelf.h"
25 #include "elf/arc.h"
26
27 static bfd_reloc_status_type arc_elf_unsupported_reloc
28   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
29 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
30   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
31 static void arc_info_to_howto_rel
32   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
33 static boolean arc_elf_object_p PARAMS ((bfd *));
34 static void arc_elf_final_write_processing PARAMS ((bfd *, boolean));
35
36 /* Try to minimize the amount of space occupied by relocation tables
37    on the ROM.  */
38 #define USE_REL
39
40 enum reloc_type
41 {
42   R_ARC_NONE = 0,
43   R_ARC_ADDR32,
44   R_ARC_B22_PCREL,
45   R_ARC_max
46 };
47
48 static reloc_howto_type elf_arc_howto_table[] =
49 {
50   /* This reloc does nothing.  */
51   HOWTO (R_ARC_NONE,            /* type */                                 
52          0,                     /* rightshift */                           
53          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
54          32,                    /* bitsize */                   
55          false,                 /* pc_relative */                          
56          0,                     /* bitpos */                               
57          complain_overflow_bitfield, /* complain_on_overflow */
58          bfd_elf_generic_reloc, /* special_function */                     
59          "R_ARC_NONE",          /* name */                                 
60          false,                 /* partial_inplace */                      
61          0,                     /* src_mask */                             
62          0,                     /* dst_mask */                             
63          false),                /* pcrel_offset */
64
65   /* A standard 32 bit relocation.  */
66   HOWTO (R_ARC_ADDR32,          /* type */                                 
67          0,                     /* rightshift */                           
68          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
69          32,                    /* bitsize */                   
70          false,                 /* pc_relative */                          
71          0,                     /* bitpos */                               
72          complain_overflow_bitfield, /* complain_on_overflow */
73          bfd_elf_generic_reloc, /* special_function */                     
74          "R_ARC_ADDR32",        /* name */
75          false,                 /* partial_inplace */                      
76          0,                     /* src_mask */                             
77          0xffffffff,            /* dst_mask */                             
78          false),                /* pcrel_offset */
79
80   /* A relative 22 bit branch; the lower two bits must be zero.  */
81   HOWTO (R_ARC_B22_PCREL,       /* type */                                 
82          2,                     /* rightshift */                           
83          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
84          22,                    /* bitsize */                   
85          true,                  /* pc_relative */                          
86          7,                     /* bitpos */                               
87          complain_overflow_signed, /* complain_on_overflow */
88          bfd_elf_generic_reloc, /* special_function */                     
89          "R_ARC_B22_PCREL",     /* name */
90          false,                 /* partial_inplace */                      
91          0,                     /* src_mask */                             
92          0x07ffff80,            /* dst_mask */                             
93          true),                 /* pcrel_offset */
94
95 };
96
97 /* Don't pretend we can deal with unsupported relocs.  */
98
99 static bfd_reloc_status_type
100 arc_elf_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
101                            output_bfd, error_message)
102      bfd *abfd;
103      arelent *reloc_entry;
104      asymbol *symbol;
105      PTR data;
106      asection *input_section;
107      bfd *output_bfd;
108      char **error_message;
109 {
110   abort ();
111 }
112
113 /* Map BFD reloc types to ARC ELF reloc types.  */
114
115 struct arc_reloc_map
116 {
117   unsigned char bfd_reloc_val;
118   unsigned char elf_reloc_val;
119 };
120
121 static const struct arc_reloc_map arc_reloc_map[] =
122 {
123   { BFD_RELOC_NONE, R_ARC_NONE, },
124   { BFD_RELOC_32, R_ARC_ADDR32 },
125   { BFD_RELOC_CTOR, R_ARC_ADDR32 },
126   { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL },
127 };
128
129 static reloc_howto_type *
130 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
131      bfd *abfd;
132      bfd_reloc_code_real_type code;
133 {
134   int i;
135
136   for (i = 0;
137        i < sizeof (arc_reloc_map) / sizeof (struct arc_reloc_map);
138        i++)
139     {
140       if (arc_reloc_map[i].bfd_reloc_val == code)
141         return &elf_arc_howto_table[arc_reloc_map[i].elf_reloc_val];
142     }
143
144   return NULL;
145 }
146
147 /* Set the howto pointer for an ARC ELF reloc.  */
148
149 static void
150 arc_info_to_howto_rel (abfd, cache_ptr, dst)
151      bfd *abfd;
152      arelent *cache_ptr;
153      Elf32_Internal_Rel *dst;
154 {
155   unsigned int r_type;
156
157   r_type = ELF32_R_TYPE (dst->r_info);
158   BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
159   cache_ptr->howto = &elf_arc_howto_table[r_type];
160 }
161
162 /* Set the right machine number for an ARC ELF file.  */
163
164 static boolean
165 arc_elf_object_p (abfd)
166      bfd *abfd;
167 {
168   int mach;
169   unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH;
170
171   switch (arch)
172     {
173     case E_ARC_MACH_BASE:
174       mach = bfd_mach_arc_base;
175       break;
176     case E_ARC_MACH_HOST:
177       mach = bfd_mach_arc_host;
178       break;
179     case E_ARC_MACH_GRAPHICS:
180       mach = bfd_mach_arc_graphics;
181       break;
182     case E_ARC_MACH_AUDIO:
183       mach = bfd_mach_arc_audio;
184       break;
185     default:
186       /* Unknown cpu type.  ??? What to do?  */
187       return false;
188     }
189
190   (void) bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
191   return true;
192 }
193
194 /* The final processing done just before writing out an ARC ELF object file.
195    This gets the ARC architecture right based on the machine number.  */
196
197 static void
198 arc_elf_final_write_processing (abfd, linker)
199      bfd *abfd;
200      boolean linker;
201 {
202   int mach;
203   unsigned long val;
204
205   switch (mach = bfd_get_mach (abfd))
206     {
207     case bfd_mach_arc_base:
208       val = E_ARC_MACH_BASE;
209       break;
210     case bfd_mach_arc_host:
211       val = E_ARC_MACH_HOST;
212       break;
213     case bfd_mach_arc_graphics:
214       val = E_ARC_MACH_GRAPHICS;
215       break;
216     case bfd_mach_arc_audio:
217       val = E_ARC_MACH_AUDIO;
218       break;
219     default:
220       return;
221     }
222
223   elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH;
224   elf_elfheader (abfd)->e_flags |= val;
225 }
226
227 #define TARGET_LITTLE_SYM       bfd_elf32_arc_vec
228 #define TARGET_LITTLE_NAME      "elf32-arc"
229 #define ELF_ARCH                bfd_arch_arc
230 #define ELF_MACHINE_CODE        EM_CYGNUS_ARC
231 #define ELF_MAXPAGESIZE         0x1000
232
233 #define elf_info_to_howto       0
234 #define elf_info_to_howto_rel   arc_info_to_howto_rel
235 #define elf_backend_object_p    arc_elf_object_p
236 #define elf_backend_final_write_processing \
237                                 arc_elf_final_write_processing
238
239 #include "elf32-target.h"