1/* moxie-specific support for 32-bit ELF.
2   Copyright (C) 2009-2017 Free Software Foundation, Inc.
3
4   Copied from elf32-fr30.c which is..
5   Copyright (C) 1998-2017 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
32static 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
82struct moxie_reloc_map
83{
84  bfd_reloc_code_real_type bfd_reloc_val;
85  unsigned int moxie_reloc_val;
86};
87
88static 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
95static reloc_howto_type *
96moxie_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
109static reloc_howto_type *
110moxie_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
126static void
127moxie_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
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
146static bfd_reloc_status_type
147moxie_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
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
197static bfd_boolean
198moxie_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
310/* Return the section that should be marked against GC for a given
311   relocation.  */
312
313static asection *
314moxie_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
327static bfd_boolean
328moxie_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
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"
392