xref: /netbsd-src/external/gpl3/gdb/dist/bfd/elf32-moxie.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* moxie-specific support for 32-bit ELF.
2    Copyright 2009, 2010, 2012 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 
33 static 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 */
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.  */
79 };
80 
81 /* Map BFD reloc types to MOXIE ELF reloc types.  */
82 
83 struct moxie_reloc_map
84 {
85   bfd_reloc_code_real_type bfd_reloc_val;
86   unsigned int moxie_reloc_val;
87 };
88 
89 static const struct moxie_reloc_map moxie_reloc_map [] =
90 {
91   { BFD_RELOC_NONE,            R_MOXIE_NONE },
92   { BFD_RELOC_32,              R_MOXIE_32 },
93   { BFD_RELOC_MOXIE_10_PCREL,  R_MOXIE_PCREL10 },
94 };
95 
96 static reloc_howto_type *
97 moxie_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 
110 static reloc_howto_type *
111 moxie_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 
127 static void
128 moxie_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 
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 
142 static bfd_reloc_status_type
143 moxie_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 
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 
193 static bfd_boolean
194 moxie_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       r_symndx = ELF32_R_SYM (rel->r_info);
226       howto  = moxie_elf_howto_table + r_type;
227       h      = NULL;
228       sym    = NULL;
229       sec    = NULL;
230 
231       if (r_symndx < symtab_hdr->sh_info)
232 	{
233 	  sym = local_syms + r_symndx;
234 	  sec = local_sections [r_symndx];
235 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
236 
237 	  name = bfd_elf_string_from_elf_section
238 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
239 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
240 	}
241       else
242 	{
243 	  bfd_boolean unresolved_reloc, warned, ignored;
244 
245 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
246 				   r_symndx, symtab_hdr, sym_hashes,
247 				   h, sec, relocation,
248 				   unresolved_reloc, warned, ignored);
249 
250 	  name = h->root.root.string;
251 	}
252 
253       if (sec != NULL && discarded_section (sec))
254 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
255 					 rel, 1, relend, howto, 0, contents);
256 
257       if (info->relocatable)
258 	continue;
259 
260       r = moxie_final_link_relocate (howto, input_bfd, input_section,
261 				     contents, rel, relocation);
262 
263       if (r != bfd_reloc_ok)
264 	{
265 	  const char * msg = NULL;
266 
267 	  switch (r)
268 	    {
269 	    case bfd_reloc_overflow:
270 	      r = info->callbacks->reloc_overflow
271 		(info, (h ? &h->root : NULL), name, howto->name,
272 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
273 	      break;
274 
275 	    case bfd_reloc_undefined:
276 	      r = info->callbacks->undefined_symbol
277 		(info, name, input_bfd, input_section, rel->r_offset,
278 		 TRUE);
279 	      break;
280 
281 	    case bfd_reloc_outofrange:
282 	      msg = _("internal error: out of range error");
283 	      break;
284 
285 	    case bfd_reloc_notsupported:
286 	      msg = _("internal error: unsupported relocation error");
287 	      break;
288 
289 	    case bfd_reloc_dangerous:
290 	      msg = _("internal error: dangerous relocation");
291 	      break;
292 
293 	    default:
294 	      msg = _("internal error: unknown error");
295 	      break;
296 	    }
297 
298 	  if (msg)
299 	    r = info->callbacks->warning
300 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
301 
302 	  if (! r)
303 	    return FALSE;
304 	}
305     }
306 
307   return TRUE;
308 }
309 
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 (info->relocatable)
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_MAXPAGESIZE		0x1
372 
373 #define TARGET_BIG_SYM          bfd_elf32_bigmoxie_vec
374 #define TARGET_BIG_NAME		"elf32-bigmoxie"
375 #define TARGET_LITTLE_SYM       bfd_elf32_littlemoxie_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