Add PC-relative branch instructions to moxie port.
[deliverable/binutils-gdb.git] / bfd / elf32-moxie.c
CommitLineData
20135e4c 1/* moxie-specific support for 32-bit ELF.
20135e4c
NC
2 Copyright 2009 Free Software Foundation, Inc.
3
4 Copied from elf32-fr30.c which is..
5 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
6 Free Software Foundation, Inc.
7
8 This file is part of BFD, the Binary File Descriptor library.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
24
25#include "sysdep.h"
26#include "bfd.h"
27#include "libbfd.h"
28#include "elf-bfd.h"
29#include "elf/moxie.h"
30
31/* Forward declarations. */
32
33static reloc_howto_type moxie_elf_howto_table [] =
34{
35 /* This reloc does nothing. */
36 HOWTO (R_MOXIE_NONE, /* type */
37 0, /* rightshift */
38 2, /* size (0 = byte, 1 = short, 2 = long) */
39 32, /* bitsize */
40 FALSE, /* pc_relative */
41 0, /* bitpos */
42 complain_overflow_bitfield, /* complain_on_overflow */
43 bfd_elf_generic_reloc, /* special_function */
44 "R_MOXIE_NONE", /* name */
45 FALSE, /* partial_inplace */
46 0, /* src_mask */
47 0, /* dst_mask */
48 FALSE), /* pcrel_offset */
49
50 /* A 32 bit absolute relocation. */
51 HOWTO (R_MOXIE_32, /* 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_MOXIE_32", /* name */
60 FALSE, /* partial_inplace */
61 0x00000000, /* src_mask */
62 0xffffffff, /* dst_mask */
63 FALSE), /* pcrel_offset */
f865a31d
AG
64
65 /* A 10 bit PC-relative relocation. */
66 HOWTO (R_MOXIE_PCREL10, /* type. */
67 1, /* rightshift. */
68 1, /* size (0 = byte, 1 = short, 2 = long). */
69 10, /* bitsize. */
70 TRUE, /* pc_relative. */
71 0, /* bitpos. */
72 complain_overflow_signed, /* complain_on_overflow. */
73 bfd_elf_generic_reloc, /* special_function. */
74 "R_MOXIE_PCREL10", /* name. */
75 FALSE, /* partial_inplace. */
76 0, /* src_mask. */
77 0x000003FF, /* dst_mask. */
78 TRUE), /* pcrel_offset. */
20135e4c
NC
79};
80\f
81/* Map BFD reloc types to MOXIE ELF reloc types. */
82
83struct moxie_reloc_map
84{
85 bfd_reloc_code_real_type bfd_reloc_val;
86 unsigned int moxie_reloc_val;
87};
88
89static const struct moxie_reloc_map moxie_reloc_map [] =
90{
f865a31d
AG
91 { BFD_RELOC_NONE, R_MOXIE_NONE },
92 { BFD_RELOC_32, R_MOXIE_32 },
93 { BFD_RELOC_MOXIE_10_PCREL, R_MOXIE_PCREL10 },
20135e4c
NC
94};
95
96static reloc_howto_type *
97moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
98 bfd_reloc_code_real_type code)
99{
100 unsigned int i;
101
102 for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
103 --i;)
104 if (moxie_reloc_map [i].bfd_reloc_val == code)
105 return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
106
107 return NULL;
108}
109
110static reloc_howto_type *
111moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
112{
113 unsigned int i;
114
115 for (i = 0;
116 i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
117 i++)
118 if (moxie_elf_howto_table[i].name != NULL
119 && strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
120 return &moxie_elf_howto_table[i];
121
122 return NULL;
123}
124
125/* Set the howto pointer for an MOXIE ELF reloc. */
126
127static void
128moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
129 arelent *cache_ptr,
130 Elf_Internal_Rela *dst)
131{
132 unsigned int r_type;
133
134 r_type = ELF32_R_TYPE (dst->r_info);
135 BFD_ASSERT (r_type < (unsigned int) R_MOXIE_max);
136 cache_ptr->howto = & moxie_elf_howto_table [r_type];
137}
138\f
139/* Perform a single relocation. By default we use the standard BFD
140 routines, but a few relocs, we have to do them ourselves. */
141
142static bfd_reloc_status_type
143moxie_final_link_relocate (reloc_howto_type *howto,
144 bfd *input_bfd,
145 asection *input_section,
146 bfd_byte *contents,
147 Elf_Internal_Rela *rel,
148 bfd_vma relocation)
149{
150 bfd_reloc_status_type r = bfd_reloc_ok;
151
152 switch (howto->type)
153 {
154 default:
155 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
156 contents, rel->r_offset,
157 relocation, rel->r_addend);
158 }
159
160 return r;
161}
162\f
163/* Relocate an MOXIE ELF section.
164
165 The RELOCATE_SECTION function is called by the new ELF backend linker
166 to handle the relocations for a section.
167
168 The relocs are always passed as Rela structures; if the section
169 actually uses Rel structures, the r_addend field will always be
170 zero.
171
172 This function is responsible for adjusting the section contents as
173 necessary, and (if using Rela relocs and generating a relocatable
174 output file) adjusting the reloc addend as necessary.
175
176 This function does not have to worry about setting the reloc
177 address or the reloc symbol index.
178
179 LOCAL_SYMS is a pointer to the swapped in local symbols.
180
181 LOCAL_SECTIONS is an array giving the section in the input file
182 corresponding to the st_shndx field of each local symbol.
183
184 The global hash table entry for the global symbols can be found
185 via elf_sym_hashes (input_bfd).
186
187 When generating relocatable output, this function must handle
188 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
189 going to be the section symbol corresponding to the output
190 section, which means that the addend must be adjusted
191 accordingly. */
192
193static bfd_boolean
194moxie_elf_relocate_section (bfd *output_bfd,
195 struct bfd_link_info *info,
196 bfd *input_bfd,
197 asection *input_section,
198 bfd_byte *contents,
199 Elf_Internal_Rela *relocs,
200 Elf_Internal_Sym *local_syms,
201 asection **local_sections)
202{
203 Elf_Internal_Shdr *symtab_hdr;
204 struct elf_link_hash_entry **sym_hashes;
205 Elf_Internal_Rela *rel;
206 Elf_Internal_Rela *relend;
207
208 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
209 sym_hashes = elf_sym_hashes (input_bfd);
210 relend = relocs + input_section->reloc_count;
211
212 for (rel = relocs; rel < relend; rel ++)
213 {
214 reloc_howto_type *howto;
215 unsigned long r_symndx;
216 Elf_Internal_Sym *sym;
217 asection *sec;
218 struct elf_link_hash_entry *h;
219 bfd_vma relocation;
220 bfd_reloc_status_type r;
221 const char *name;
222 int r_type;
223
224 r_type = ELF32_R_TYPE (rel->r_info);
225
226 r_symndx = ELF32_R_SYM (rel->r_info);
227
228 howto = moxie_elf_howto_table + ELF32_R_TYPE (rel->r_info);
229 h = NULL;
230 sym = NULL;
231 sec = NULL;
232
233 if (r_symndx < symtab_hdr->sh_info)
234 {
235 sym = local_syms + r_symndx;
236 sec = local_sections [r_symndx];
237 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
238
239 name = bfd_elf_string_from_elf_section
240 (input_bfd, symtab_hdr->sh_link, sym->st_name);
241 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
242 }
243 else
244 {
245 bfd_boolean unresolved_reloc, warned;
246
247 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
248 r_symndx, symtab_hdr, sym_hashes,
249 h, sec, relocation,
250 unresolved_reloc, warned);
251
252 name = h->root.root.string;
253 }
254
255 if (sec != NULL && elf_discarded_section (sec))
256 {
257 /* For relocs against symbols from removed linkonce sections,
258 or sections discarded by a linker script, we just want the
259 section contents zeroed. Avoid any special processing. */
260 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
261 rel->r_info = 0;
262 rel->r_addend = 0;
263 continue;
264 }
265
266 if (info->relocatable)
267 continue;
268
269 r = moxie_final_link_relocate (howto, input_bfd, input_section,
270 contents, rel, relocation);
271
272 if (r != bfd_reloc_ok)
273 {
274 const char * msg = NULL;
275
276 switch (r)
277 {
278 case bfd_reloc_overflow:
279 r = info->callbacks->reloc_overflow
280 (info, (h ? &h->root : NULL), name, howto->name,
281 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
282 break;
283
284 case bfd_reloc_undefined:
285 r = info->callbacks->undefined_symbol
286 (info, name, input_bfd, input_section, rel->r_offset,
287 TRUE);
288 break;
289
290 case bfd_reloc_outofrange:
291 msg = _("internal error: out of range error");
292 break;
293
294 case bfd_reloc_notsupported:
295 msg = _("internal error: unsupported relocation error");
296 break;
297
298 case bfd_reloc_dangerous:
299 msg = _("internal error: dangerous relocation");
300 break;
301
302 default:
303 msg = _("internal error: unknown error");
304 break;
305 }
306
307 if (msg)
308 r = info->callbacks->warning
309 (info, msg, name, input_bfd, input_section, rel->r_offset);
310
311 if (! r)
312 return FALSE;
313 }
314 }
315
316 return TRUE;
317}
318\f
319/* Return the section that should be marked against GC for a given
320 relocation. */
321
322static asection *
323moxie_elf_gc_mark_hook (asection *sec,
324 struct bfd_link_info *info,
325 Elf_Internal_Rela *rel,
326 struct elf_link_hash_entry *h,
327 Elf_Internal_Sym *sym)
328{
329 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
330}
331
332/* Look through the relocs for a section during the first phase.
333 Since we don't do .gots or .plts, we just need to consider the
334 virtual table relocs for gc. */
335
336static bfd_boolean
337moxie_elf_check_relocs (bfd *abfd,
338 struct bfd_link_info *info,
339 asection *sec,
340 const Elf_Internal_Rela *relocs)
341{
342 Elf_Internal_Shdr *symtab_hdr;
343 struct elf_link_hash_entry **sym_hashes;
344 const Elf_Internal_Rela *rel;
345 const Elf_Internal_Rela *rel_end;
346
347 if (info->relocatable)
348 return TRUE;
349
350 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
351 sym_hashes = elf_sym_hashes (abfd);
352
353 rel_end = relocs + sec->reloc_count;
354 for (rel = relocs; rel < rel_end; rel++)
355 {
356 struct elf_link_hash_entry *h;
357 unsigned long r_symndx;
358
359 r_symndx = ELF32_R_SYM (rel->r_info);
360 if (r_symndx < symtab_hdr->sh_info)
361 h = NULL;
362 else
363 {
364 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
365 while (h->root.type == bfd_link_hash_indirect
366 || h->root.type == bfd_link_hash_warning)
367 h = (struct elf_link_hash_entry *) h->root.u.i.link;
368 }
369 }
370
371 return TRUE;
372}
373\f
374#define ELF_ARCH bfd_arch_moxie
375#define ELF_MACHINE_CODE EM_MOXIE
376#define ELF_MAXPAGESIZE 0x1
377
378#define TARGET_BIG_SYM bfd_elf32_moxie_vec
379#define TARGET_BIG_NAME "elf32-moxie"
380
381#define elf_info_to_howto_rel NULL
382#define elf_info_to_howto moxie_info_to_howto_rela
383#define elf_backend_relocate_section moxie_elf_relocate_section
384#define elf_backend_gc_mark_hook moxie_elf_gc_mark_hook
385#define elf_backend_check_relocs moxie_elf_check_relocs
386
387#define elf_backend_can_gc_sections 1
388#define elf_backend_rela_normal 1
389
390#define bfd_elf32_bfd_reloc_type_lookup moxie_reloc_type_lookup
391#define bfd_elf32_bfd_reloc_name_lookup moxie_reloc_name_lookup
392
393#include "elf32-target.h"
This page took 0.046267 seconds and 4 git commands to generate.