xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elf32-moxie.c (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
1 /* moxie-specific support for 32-bit ELF.
2    Copyright (C) 2009-2020 Free Software Foundation, Inc.
3 
4    Copied from elf32-fr30.c which is..
5    Copyright (C) 1998-2020 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 
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 bfd_boolean
127 moxie_info_to_howto_rela (bfd *abfd,
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 (_("%pB: unsupported relocation type %#x"),
138 			  abfd, r_type);
139       bfd_set_error (bfd_error_bad_value);
140       return FALSE;
141     }
142   cache_ptr->howto = & moxie_elf_howto_table [r_type];
143   return TRUE;
144 }
145 
146 /* Perform a single relocation.  By default we use the standard BFD
147    routines, but a few relocs, we have to do them ourselves.  */
148 
149 static bfd_reloc_status_type
150 moxie_final_link_relocate (reloc_howto_type *howto,
151 			   bfd *input_bfd,
152 			   asection *input_section,
153 			   bfd_byte *contents,
154 			   Elf_Internal_Rela *rel,
155 			   bfd_vma relocation)
156 {
157   bfd_reloc_status_type r = bfd_reloc_ok;
158 
159   switch (howto->type)
160     {
161     default:
162       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
163 				    contents, rel->r_offset,
164 				    relocation, rel->r_addend);
165     }
166 
167   return r;
168 }
169 
170 /* Relocate an MOXIE ELF section.
171 
172    The RELOCATE_SECTION function is called by the new ELF backend linker
173    to handle the relocations for a section.
174 
175    The relocs are always passed as Rela structures; if the section
176    actually uses Rel structures, the r_addend field will always be
177    zero.
178 
179    This function is responsible for adjusting the section contents as
180    necessary, and (if using Rela relocs and generating a relocatable
181    output file) adjusting the reloc addend as necessary.
182 
183    This function does not have to worry about setting the reloc
184    address or the reloc symbol index.
185 
186    LOCAL_SYMS is a pointer to the swapped in local symbols.
187 
188    LOCAL_SECTIONS is an array giving the section in the input file
189    corresponding to the st_shndx field of each local symbol.
190 
191    The global hash table entry for the global symbols can be found
192    via elf_sym_hashes (input_bfd).
193 
194    When generating relocatable output, this function must handle
195    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
196    going to be the section symbol corresponding to the output
197    section, which means that the addend must be adjusted
198    accordingly.  */
199 
200 static bfd_boolean
201 moxie_elf_relocate_section (bfd *output_bfd,
202 			    struct bfd_link_info *info,
203 			    bfd *input_bfd,
204 			    asection *input_section,
205 			    bfd_byte *contents,
206 			    Elf_Internal_Rela *relocs,
207 			    Elf_Internal_Sym *local_syms,
208 			    asection **local_sections)
209 {
210   Elf_Internal_Shdr *symtab_hdr;
211   struct elf_link_hash_entry **sym_hashes;
212   Elf_Internal_Rela *rel;
213   Elf_Internal_Rela *relend;
214 
215   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
216   sym_hashes = elf_sym_hashes (input_bfd);
217   relend     = relocs + input_section->reloc_count;
218 
219   for (rel = relocs; rel < relend; rel ++)
220     {
221       reloc_howto_type *howto;
222       unsigned long r_symndx;
223       Elf_Internal_Sym *sym;
224       asection *sec;
225       struct elf_link_hash_entry *h;
226       bfd_vma relocation;
227       bfd_reloc_status_type r;
228       const char *name;
229       int r_type;
230 
231       r_type = ELF32_R_TYPE (rel->r_info);
232       r_symndx = ELF32_R_SYM (rel->r_info);
233       howto  = moxie_elf_howto_table + r_type;
234       h      = NULL;
235       sym    = NULL;
236       sec    = NULL;
237 
238       if (r_symndx < symtab_hdr->sh_info)
239 	{
240 	  sym = local_syms + r_symndx;
241 	  sec = local_sections [r_symndx];
242 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
243 
244 	  name = bfd_elf_string_from_elf_section
245 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
246 	  name = name == NULL ? bfd_section_name (sec) : name;
247 	}
248       else
249 	{
250 	  bfd_boolean unresolved_reloc, warned, ignored;
251 
252 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
253 				   r_symndx, symtab_hdr, sym_hashes,
254 				   h, sec, relocation,
255 				   unresolved_reloc, warned, ignored);
256 
257 	  name = h->root.root.string;
258 	}
259 
260       if (sec != NULL && discarded_section (sec))
261 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
262 					 rel, 1, relend, howto, 0, contents);
263 
264       if (bfd_link_relocatable (info))
265 	continue;
266 
267       r = moxie_final_link_relocate (howto, input_bfd, input_section,
268 				     contents, rel, relocation);
269 
270       if (r != bfd_reloc_ok)
271 	{
272 	  const char * msg = NULL;
273 
274 	  switch (r)
275 	    {
276 	    case bfd_reloc_overflow:
277 	      (*info->callbacks->reloc_overflow)
278 		(info, (h ? &h->root : NULL), name, howto->name,
279 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
280 	      break;
281 
282 	    case bfd_reloc_undefined:
283 	      (*info->callbacks->undefined_symbol)
284 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
285 	      break;
286 
287 	    case bfd_reloc_outofrange:
288 	      msg = _("internal error: out of range error");
289 	      break;
290 
291 	    case bfd_reloc_notsupported:
292 	      msg = _("internal error: unsupported relocation error");
293 	      break;
294 
295 	    case bfd_reloc_dangerous:
296 	      msg = _("internal error: dangerous relocation");
297 	      break;
298 
299 	    default:
300 	      msg = _("internal error: unknown error");
301 	      break;
302 	    }
303 
304 	  if (msg)
305 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
306 					 input_section, rel->r_offset);
307 	}
308     }
309 
310   return TRUE;
311 }
312 
313 /* Return the section that should be marked against GC for a given
314    relocation.  */
315 
316 static asection *
317 moxie_elf_gc_mark_hook (asection *sec,
318 			struct bfd_link_info *info,
319 			Elf_Internal_Rela *rel,
320 			struct elf_link_hash_entry *h,
321 			Elf_Internal_Sym *sym)
322 {
323   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
324 }
325 
326 /* Look through the relocs for a section during the first phase.
327    Since we don't do .gots or .plts, we just need to consider the
328    virtual table relocs for gc.  */
329 
330 static bfd_boolean
331 moxie_elf_check_relocs (bfd *abfd,
332 			struct bfd_link_info *info,
333 			asection *sec,
334 			const Elf_Internal_Rela *relocs)
335 {
336   Elf_Internal_Shdr *symtab_hdr;
337   struct elf_link_hash_entry **sym_hashes;
338   const Elf_Internal_Rela *rel;
339   const Elf_Internal_Rela *rel_end;
340 
341   if (bfd_link_relocatable (info))
342     return TRUE;
343 
344   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
345   sym_hashes = elf_sym_hashes (abfd);
346 
347   rel_end = relocs + sec->reloc_count;
348   for (rel = relocs; rel < rel_end; rel++)
349     {
350       struct elf_link_hash_entry *h;
351       unsigned long r_symndx;
352 
353       r_symndx = ELF32_R_SYM (rel->r_info);
354       if (r_symndx < symtab_hdr->sh_info)
355 	h = NULL;
356       else
357 	{
358 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
359 	  while (h->root.type == bfd_link_hash_indirect
360 		 || h->root.type == bfd_link_hash_warning)
361 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
362 	}
363     }
364 
365   return TRUE;
366 }
367 
368 #define ELF_ARCH		bfd_arch_moxie
369 #define ELF_MACHINE_CODE	EM_MOXIE
370 #define ELF_MACHINE_ALT1	EM_MOXIE_OLD
371 #define ELF_MAXPAGESIZE		0x1
372 
373 #define TARGET_BIG_SYM		moxie_elf32_be_vec
374 #define TARGET_BIG_NAME		"elf32-bigmoxie"
375 #define TARGET_LITTLE_SYM	moxie_elf32_le_vec
376 #define TARGET_LITTLE_NAME	"elf32-littlemoxie"
377 
378 #define elf_info_to_howto_rel			NULL
379 #define elf_info_to_howto			moxie_info_to_howto_rela
380 #define elf_backend_relocate_section		moxie_elf_relocate_section
381 #define elf_backend_gc_mark_hook		moxie_elf_gc_mark_hook
382 #define elf_backend_check_relocs		moxie_elf_check_relocs
383 
384 #define elf_backend_can_gc_sections		1
385 #define elf_backend_rela_normal			1
386 
387 #define bfd_elf32_bfd_reloc_type_lookup		moxie_reloc_type_lookup
388 #define bfd_elf32_bfd_reloc_name_lookup		moxie_reloc_name_lookup
389 
390 #include "elf32-target.h"
391