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