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