xref: /netbsd-src/external/gpl3/gdb/dist/bfd/elf32-ft32.c (revision 1580a27b92f58fcdcb23fdfbc04a7c2b54a0b7c8)
1 /* ft32-specific support for 32-bit ELF.
2    Copyright (C) 2013-2016 Free Software Foundation, Inc.
3 
4    Copied from elf32-moxie.c which is..
5    Copyright (C) 2009-2016 Free Software Foundation, Inc.
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/ft32.h"
30 
31 /* Forward declarations.  */
32 
33 static reloc_howto_type ft32_elf_howto_table [] =
34 {
35   /* This reloc does nothing.  */
36   HOWTO (R_FT32_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_FT32_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 
52   HOWTO (R_FT32_32,		/* type */
53 	 0,			/* rightshift */
54 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
55 	 32,			/* bitsize */
56 	 FALSE,			/* pc_relative */
57 	 0,			/* bitpos */
58 	 complain_overflow_bitfield, /* complain_on_overflow */
59 	 bfd_elf_generic_reloc,	/* special_function */
60 	 "R_FT32_32",		/* name */
61 	 FALSE,			/* partial_inplace */
62 	 0x00000000,		/* src_mask */
63 	 0xffffffff,		/* dst_mask */
64 	 FALSE),		/* pcrel_offset */
65 
66   HOWTO (R_FT32_16,		/* type */
67 	 0,			/* rightshift */
68 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
69 	 16,			/* bitsize */
70 	 FALSE,			/* pc_relative */
71 	 0,			/* bitpos */
72 	 complain_overflow_bitfield, /* complain_on_overflow */
73 	 bfd_elf_generic_reloc,	/* special_function */
74 	 "R_FT32_16",		/* name */
75 	 FALSE,			/* partial_inplace */
76 	 0x00000000,		/* src_mask */
77 	 0x0000ffff,		/* dst_mask */
78 	 FALSE),		/* pcrel_offset */
79 
80   HOWTO (R_FT32_8,		/* type */
81 	 0,			/* rightshift */
82 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
83 	 8,			/* bitsize */
84 	 FALSE,			/* pc_relative */
85 	 0,			/* bitpos */
86 	 complain_overflow_signed, /* complain_on_overflow */
87 	 bfd_elf_generic_reloc,	/* special_function */
88 	 "R_FT32_8",		/* name */
89 	 FALSE,			/* partial_inplace */
90 	 0x00000000,		/* src_mask */
91 	 0x000000ff,		/* dst_mask */
92 	 FALSE),		/* pcrel_offset */
93 
94   HOWTO (R_FT32_10,		/* type */
95 	 0,			/* rightshift */
96 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
97 	 10,			/* bitsize */
98 	 FALSE,			/* pc_relative */
99 	 4,			/* bitpos */
100 	 complain_overflow_signed, /* complain_on_overflow */
101 	 bfd_elf_generic_reloc,	/* special_function */
102 	 "R_FT32_10",		/* name */
103 	 FALSE,			/* partial_inplace */
104 	 0x00000000,		/* src_mask */
105 	 0x00003ff0,		/* dst_mask */
106 	 FALSE),		/* pcrel_offset */
107 
108   HOWTO (R_FT32_20,		/* type */
109 	 0,			/* rightshift */
110 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
111 	 20,			/* bitsize */
112 	 FALSE,			/* pc_relative */
113 	 0,			/* bitpos */
114 	 complain_overflow_dont, /* complain_on_overflow */
115 	 bfd_elf_generic_reloc,	/* special_function */
116 	 "R_FT32_20",		/* name */
117 	 FALSE,			/* partial_inplace */
118 	 0x00000000,		/* src_mask */
119 	 0x000fffff,		/* dst_mask */
120 	 FALSE),		/* pcrel_offset */
121 
122   HOWTO (R_FT32_17,		/* type */
123 	 0,			/* rightshift */
124 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
125 	 17,			/* bitsize */
126 	 FALSE,			/* pc_relative */
127 	 0,			/* bitpos */
128 	 complain_overflow_dont, /* complain_on_overflow */
129 	 bfd_elf_generic_reloc,	/* special_function */
130 	 "R_FT32_17",		/* name */
131 	 FALSE,			/* partial_inplace */
132 	 0x00000000,		/* src_mask */
133 	 0x0001ffff,		/* dst_mask */
134 	 FALSE),		/* pcrel_offset */
135 
136   HOWTO (R_FT32_18,		/* type */
137 	 2,			/* rightshift */
138 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
139 	 18,			/* bitsize */
140 	 FALSE,			/* pc_relative */
141 	 0,			/* bitpos */
142 	 complain_overflow_signed, /* complain_on_overflow */
143 	 bfd_elf_generic_reloc,	/* special_function */
144 	 "R_FT32_18",		/* name */
145 	 FALSE,		/* partial_inplace */
146 	 0x00000000,		/* src_mask */
147 	 0x0003ffff,		/* dst_mask */
148 	 FALSE),		/* pcrel_offset */
149 
150 };
151 
152 /* Map BFD reloc types to FT32 ELF reloc types.  */
153 
154 struct ft32_reloc_map
155 {
156   bfd_reloc_code_real_type bfd_reloc_val;
157   unsigned int ft32_reloc_val;
158 };
159 
160 static const struct ft32_reloc_map ft32_reloc_map [] =
161 {
162   { BFD_RELOC_NONE,            R_FT32_NONE },
163   { BFD_RELOC_32,              R_FT32_32 },
164   { BFD_RELOC_16,              R_FT32_16 },
165   { BFD_RELOC_8,               R_FT32_8 },
166   { BFD_RELOC_FT32_10,           R_FT32_10 },
167   { BFD_RELOC_FT32_20,           R_FT32_20 },
168   { BFD_RELOC_FT32_17,           R_FT32_17 },
169   { BFD_RELOC_FT32_18,           R_FT32_18 },
170 };
171 
172 static reloc_howto_type *
173 ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
174 			 bfd_reloc_code_real_type code)
175 {
176   unsigned int i;
177 
178   for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]);
179        --i;)
180     if (ft32_reloc_map [i].bfd_reloc_val == code)
181       return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val];
182 
183   return NULL;
184 }
185 
186 static reloc_howto_type *
187 ft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
188 {
189   unsigned int i;
190 
191   for (i = 0;
192        i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]);
193        i++)
194     if (ft32_elf_howto_table[i].name != NULL
195 	&& strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0)
196       return &ft32_elf_howto_table[i];
197 
198   return NULL;
199 }
200 
201 /* Set the howto pointer for an FT32 ELF reloc.  */
202 
203 static void
204 ft32_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
205 			  arelent *cache_ptr,
206 			  Elf_Internal_Rela *dst)
207 {
208   unsigned int r_type;
209 
210   r_type = ELF32_R_TYPE (dst->r_info);
211   BFD_ASSERT (r_type < (unsigned int) R_FT32_max);
212   cache_ptr->howto = & ft32_elf_howto_table [r_type];
213 }
214 
215 /* Relocate an FT32 ELF section.
216 
217    The RELOCATE_SECTION function is called by the new ELF backend linker
218    to handle the relocations for a section.
219 
220    The relocs are always passed as Rela structures; if the section
221    actually uses Rel structures, the r_addend field will always be
222    zero.
223 
224    This function is responsible for adjusting the section contents as
225    necessary, and (if using Rela relocs and generating a relocatable
226    output file) adjusting the reloc addend as necessary.
227 
228    This function does not have to worry about setting the reloc
229    address or the reloc symbol index.
230 
231    LOCAL_SYMS is a pointer to the swapped in local symbols.
232 
233    LOCAL_SECTIONS is an array giving the section in the input file
234    corresponding to the st_shndx field of each local symbol.
235 
236    The global hash table entry for the global symbols can be found
237    via elf_sym_hashes (input_bfd).
238 
239    When generating relocatable output, this function must handle
240    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
241    going to be the section symbol corresponding to the output
242    section, which means that the addend must be adjusted
243    accordingly.  */
244 
245 static bfd_boolean
246 ft32_elf_relocate_section (bfd *output_bfd,
247 			    struct bfd_link_info *info,
248 			    bfd *input_bfd,
249 			    asection *input_section,
250 			    bfd_byte *contents,
251 			    Elf_Internal_Rela *relocs,
252 			    Elf_Internal_Sym *local_syms,
253 			    asection **local_sections)
254 {
255   Elf_Internal_Shdr *symtab_hdr;
256   struct elf_link_hash_entry **sym_hashes;
257   Elf_Internal_Rela *rel;
258   Elf_Internal_Rela *relend;
259 
260   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
261   sym_hashes = elf_sym_hashes (input_bfd);
262   relend     = relocs + input_section->reloc_count;
263 
264   for (rel = relocs; rel < relend; rel ++)
265     {
266       reloc_howto_type *howto;
267       unsigned long r_symndx;
268       Elf_Internal_Sym *sym;
269       asection *sec;
270       struct elf_link_hash_entry *h;
271       bfd_vma relocation;
272       bfd_reloc_status_type r;
273       const char *name;
274       int r_type;
275 
276       r_type = ELF32_R_TYPE (rel->r_info);
277       r_symndx = ELF32_R_SYM (rel->r_info);
278       howto  = ft32_elf_howto_table + r_type;
279       h      = NULL;
280       sym    = NULL;
281       sec    = NULL;
282 
283       if (r_symndx < symtab_hdr->sh_info)
284 	{
285 	  sym = local_syms + r_symndx;
286 	  sec = local_sections [r_symndx];
287 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
288 
289 	  name = bfd_elf_string_from_elf_section
290 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
291 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
292 	}
293       else
294 	{
295 	  bfd_boolean unresolved_reloc, warned, ignored;
296 
297 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
298 				   r_symndx, symtab_hdr, sym_hashes,
299 				   h, sec, relocation,
300 				   unresolved_reloc, warned, ignored);
301 
302 	  name = h->root.root.string;
303 	}
304 
305       if (sec != NULL && discarded_section (sec))
306 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
307 					 rel, 1, relend, howto, 0, contents);
308 
309       if (bfd_link_relocatable (info))
310 	continue;
311 
312       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
313 				    contents, rel->r_offset,
314 				    relocation, rel->r_addend);
315 
316       if (r != bfd_reloc_ok)
317 	{
318 	  const char * msg = NULL;
319 
320 	  switch (r)
321 	    {
322 	    case bfd_reloc_overflow:
323 	      (*info->callbacks->reloc_overflow)
324 		(info, (h ? &h->root : NULL), name, howto->name,
325 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
326 	      break;
327 
328 	    case bfd_reloc_undefined:
329 	      (*info->callbacks->undefined_symbol)
330 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
331 	      break;
332 
333 	    case bfd_reloc_outofrange:
334 	      msg = _("internal error: out of range error");
335 	      break;
336 
337 	    case bfd_reloc_notsupported:
338 	      msg = _("internal error: unsupported relocation error");
339 	      break;
340 
341 	    case bfd_reloc_dangerous:
342 	      msg = _("internal error: dangerous relocation");
343 	      break;
344 
345 	    default:
346 	      msg = _("internal error: unknown error");
347 	      break;
348 	    }
349 
350 	  if (msg)
351 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
352 					 input_section, rel->r_offset);
353 	}
354     }
355 
356   return TRUE;
357 }
358 
359 #define ELF_ARCH		bfd_arch_ft32
360 #define ELF_MACHINE_CODE	EM_FT32
361 #define ELF_MAXPAGESIZE		0x1
362 
363 #define TARGET_LITTLE_SYM       ft32_elf32_vec
364 #define TARGET_LITTLE_NAME	"elf32-ft32"
365 
366 #define elf_info_to_howto_rel			NULL
367 #define elf_info_to_howto			ft32_info_to_howto_rela
368 #define elf_backend_relocate_section		ft32_elf_relocate_section
369 
370 #define elf_backend_can_gc_sections		1
371 #define elf_backend_rela_normal			1
372 
373 #define bfd_elf32_bfd_reloc_type_lookup		ft32_reloc_type_lookup
374 #define bfd_elf32_bfd_reloc_name_lookup		ft32_reloc_name_lookup
375 
376 #include "elf32-target.h"
377