xref: /netbsd-src/external/gpl3/binutils/dist/bfd/elf32-arc.c (revision a24efa7dea9f1f56c3bdb15a927d3516792ace1c)
1 /* ARC-specific support for 32-bit ELF
2    Copyright (C) 1994-2015 Free Software Foundation, Inc.
3    Contributed by Cupertino Miranda (cmiranda@synopsys.com).
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/arc.h"
27 #include "libiberty.h"
28 #include "opcode/arc-func.h"
29 
30 #define ARC_DEBUG(...)
31 #define DEBUG(...) printf (__ARGV__)
32 #define DEBUG_ARC_RELOC(A)
33 
34 struct arc_local_data
35 {
36   bfd_vma	  sdata_begin_symbol_vma;
37   asection *      sdata_output_section;
38   bfd_vma	  got_symbol_vma;
39 };
40 
41 struct arc_local_data global_arc_data =
42 {
43   .sdata_begin_symbol_vma = 0,
44   .sdata_output_section = NULL,
45   .got_symbol_vma = 0,
46 };
47 
48 struct dynamic_sections
49 {
50   bfd_boolean	  initialized;
51   asection *      sgot;
52   asection *      srelgot;
53   asection *      sgotplt;
54   asection *      sdyn;
55   asection *      splt;
56   asection *      srelplt;
57 };
58 
59 static struct dynamic_sections
60 arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info);
61 
62 enum dyn_section_types
63 {
64   got = 0,
65   relgot,
66   gotplt,
67   dyn,
68   plt,
69   relplt,
70   DYN_SECTION_TYPES_END
71 };
72 
73 const char * dyn_section_names[DYN_SECTION_TYPES_END] =
74 {
75   ".got",
76   ".rela.got",
77   ".got.plt",
78   ".dynamic",
79   ".plt",
80   ".rela.plt"
81 };
82 
83 /* The default symbols representing the init and fini dyn values.
84    TODO: Check what is the relation of those strings with arclinux.em
85    and DT_INIT.  */
86 #define INIT_SYM_STRING "_init"
87 #define FINI_SYM_STRING "_fini"
88 
89 char * init_str = INIT_SYM_STRING;
90 char * fini_str = FINI_SYM_STRING;
91 
92 
93 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
94       case VALUE: \
95 	return #TYPE; \
96 	break;
97 
98 static ATTRIBUTE_UNUSED const char *
99 reloc_type_to_name (unsigned int type)
100 {
101   switch (type)
102     {
103       #include "elf/arc-reloc.def"
104 
105       default:
106 	return "UNKNOWN";
107 	break;
108     }
109 }
110 #undef ARC_RELOC_HOWTO
111 
112 /* Try to minimize the amount of space occupied by relocation tables
113    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
114 
115 #define USE_REL 1
116 
117 static ATTRIBUTE_UNUSED bfd_boolean
118 is_reloc_PC_relative (reloc_howto_type *howto)
119 {
120   return (strstr (howto->name, "PC") != NULL) ? TRUE : FALSE;
121 }
122 
123 static bfd_boolean
124 is_reloc_SDA_relative (reloc_howto_type *howto)
125 {
126   return (strstr (howto->name, "SDA") != NULL) ? TRUE : FALSE;
127 }
128 
129 static bfd_boolean
130 is_reloc_for_GOT (reloc_howto_type * howto)
131 {
132   return (strstr (howto->name, "GOT") != NULL) ? TRUE : FALSE;
133 }
134 
135 static bfd_boolean
136 is_reloc_for_PLT (reloc_howto_type * howto)
137 {
138   return (strstr (howto->name, "PLT") != NULL) ? TRUE : FALSE;
139 }
140 
141 #define arc_bfd_get_8(A,B,C) bfd_get_8(A,B)
142 #define arc_bfd_get_16(A,B,C) bfd_get_16(A,B)
143 #define arc_bfd_put_8(A,B,C,D) bfd_put_8(A,B,C)
144 #define arc_bfd_put_16(A,B,C,D) bfd_put_16(A,B,C)
145 
146 static long
147 arc_bfd_get_32 (bfd * abfd, void *loc, asection * input_section)
148 {
149   long insn = bfd_get_32 (abfd, loc);
150 
151   if (!bfd_big_endian (abfd)
152       && input_section
153       && (input_section->flags & SEC_CODE))
154     insn = ((0x0000fffff & insn) << 16) | ((0xffff0000 & insn) >> 16);
155 
156   return insn;
157 }
158 
159 static void
160 arc_bfd_put_32 (bfd * abfd, long insn, void *loc, asection * input_section)
161 {
162   if (!bfd_big_endian (abfd)
163       && input_section
164       && (input_section->flags & SEC_CODE))
165     insn = ((0x0000fffff & insn) << 16) | ((0xffff0000 & insn) >> 16);
166 
167   bfd_put_32 (abfd, insn, loc);
168 }
169 
170 static bfd_reloc_status_type
171 arc_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED,
172 	       arelent *reloc_entry,
173 	       asymbol *symbol_in,
174 	       void *data ATTRIBUTE_UNUSED,
175 	       asection *input_section,
176 	       bfd *output_bfd,
177 	       char ** error_message ATTRIBUTE_UNUSED)
178 {
179   if (output_bfd != NULL)
180     {
181       reloc_entry->address += input_section->output_offset;
182 
183       /* In case of relocateable link and if the reloc is against a
184 	 section symbol, the addend needs to be adjusted according to
185 	 where the section symbol winds up in the output section.  */
186       if ((symbol_in->flags & BSF_SECTION_SYM) && symbol_in->section)
187 	reloc_entry->addend += symbol_in->section->output_offset;
188 
189       return bfd_reloc_ok;
190     }
191 
192   return bfd_reloc_continue;
193 }
194 
195 
196 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
197   TYPE = VALUE,
198 enum howto_list
199 {
200 #include "elf/arc-reloc.def"
201   HOWTO_LIST_LAST
202 };
203 #undef ARC_RELOC_HOWTO
204 
205 #define ARC_RELOC_HOWTO(TYPE, VALUE, RSIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
206   [TYPE] = HOWTO (R_##TYPE, 0, RSIZE, BITSIZE, FALSE, 0, complain_overflow_##OVERFLOW, arc_elf_reloc, #TYPE, FALSE, 0, 0, FALSE),
207 
208 static struct reloc_howto_struct elf_arc_howto_table[] =
209 {
210 #include "elf/arc-reloc.def"
211 /* Example of what is generated by the preprocessor.  Currently kept as an example.
212  HOWTO (R_ARC_NONE, // Type.
213     0, // Rightshift.
214     2, // Size (0 = byte, 1 = short, 2 = long).
215     32, // Bitsize.
216     FALSE, // PC_relative.
217     0, // Bitpos.
218     complain_overflow_bitfield, // Complain_on_overflow.
219     bfd_elf_generic_reloc, // Special_function.
220     "R_ARC_NONE", // Name.
221     TRUE, // Partial_inplace.
222     0, // Src_mask.
223     0, // Dst_mask.
224     FALSE), // PCrel_offset.
225 */
226 };
227 #undef ARC_RELOC_HOWTO
228 
229 static void arc_elf_howto_init (void)
230 {
231 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
232   elf_arc_howto_table[TYPE].pc_relative = \
233     (strstr (#FORMULA, " P ") != NULL || strstr (#FORMULA, " PDATA ") != NULL);
234 
235   #include "elf/arc-reloc.def"
236 }
237 #undef ARC_RELOC_HOWTO
238 
239 
240 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
241   [TYPE] = VALUE,
242 const int howto_table_lookup[] =
243 {
244   #include "elf/arc-reloc.def"
245 };
246 #undef ARC_RELOC_HOWTO
247 
248 #define ARC_ELF_HOWTO(r_type) \
249   (&elf_arc_howto_table[r_type])
250 
251 /* Map BFD reloc types to ARC ELF reloc types.  */
252 
253 struct arc_reloc_map
254 {
255   bfd_reloc_code_real_type bfd_reloc_val;
256   unsigned char   elf_reloc_val;
257 };
258 
259 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
260   { BFD_RELOC_##TYPE, R_##TYPE },
261 static const struct arc_reloc_map arc_reloc_map[] =
262 {
263   #include "elf/arc-reloc.def"
264   {BFD_RELOC_NONE,  R_ARC_NONE},
265   {BFD_RELOC_8,  R_ARC_8},
266   {BFD_RELOC_16, R_ARC_16},
267   {BFD_RELOC_24, R_ARC_24},
268   {BFD_RELOC_32, R_ARC_32},
269 };
270 #undef ARC_RELOC_HOWTO
271 
272 static reloc_howto_type *
273 bfd_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
274 				 bfd_reloc_code_real_type code)
275 {
276   unsigned int i;
277   static int fully_initialized = FALSE;
278 
279   if (fully_initialized == FALSE)
280     {
281       arc_elf_howto_init ();
282       fully_initialized = TRUE; /* TODO: CHECK THIS IF IT STOPS WORKING.  */
283     }
284 
285   for (i = ARRAY_SIZE (arc_reloc_map); i--;)
286     {
287       if (arc_reloc_map[i].bfd_reloc_val == code)
288 	return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
289     }
290 
291   return NULL;
292 }
293 
294 static reloc_howto_type *
295 bfd_elf32_bfd_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, const char *r_name)
296 {
297   unsigned int i;
298 
299   for (i = 0; i < ARRAY_SIZE (elf_arc_howto_table); i++)
300     if (elf_arc_howto_table[i].name != NULL
301 	&& strcasecmp (elf_arc_howto_table[i].name, r_name) == 0)
302       return elf_arc_howto_table + i;
303 
304   return NULL;
305 }
306 
307 
308 /* Set the howto pointer for an ARC ELF reloc.  */
309 static void
310 arc_info_to_howto_rel (bfd * abfd ATTRIBUTE_UNUSED,
311 		       arelent * cache_ptr,
312 		       Elf_Internal_Rela * dst)
313 {
314   unsigned int r_type;
315 
316   r_type = ELF32_R_TYPE (dst->r_info);
317   BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
318   cache_ptr->howto = &elf_arc_howto_table[r_type];
319 }
320 
321 /* Set the right machine number for an ARC ELF file.  */
322 static bfd_boolean
323 arc_elf_object_p (bfd * abfd)
324 {
325   /* Make sure this is initialised, or you'll have the potential of passing
326      garbage---or misleading values---into the call to
327      bfd_default_set_arch_mach ().  */
328   int		  mach = bfd_mach_arc_arc700;
329   unsigned long   arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH_MSK;
330   unsigned	  e_machine = elf_elfheader (abfd)->e_machine;
331 
332   if (e_machine == EM_ARC_COMPACT || e_machine == EM_ARC_COMPACT2)
333     {
334       switch (arch)
335 	{
336 	  case E_ARC_MACH_ARC600:
337 	    mach = bfd_mach_arc_arc600;
338 	    break;
339 	  case E_ARC_MACH_ARC601:
340 	    mach = bfd_mach_arc_arc601;
341 	    break;
342 	  case E_ARC_MACH_ARC700:
343 	    mach = bfd_mach_arc_arc700;
344 	    break;
345 	  case EF_ARC_CPU_ARCV2HS:
346 	  case EF_ARC_CPU_ARCV2EM:
347 	    mach = bfd_mach_arc_arcv2;
348 	    break;
349 	  default:
350 	    mach = (e_machine == EM_ARC_COMPACT) ?
351 	      bfd_mach_arc_arc700 : bfd_mach_arc_arcv2;
352 	    break;
353 	}
354     }
355   else
356     {
357       if (e_machine == EM_ARC)
358 	{
359 	  (*_bfd_error_handler)
360 	    (_("Error: The ARC4 architecture is no longer supported.\n"));
361 	  return FALSE;
362 	}
363       else
364 	{
365 	  (*_bfd_error_handler)
366 	    (_("Warning: unset or old architecture flags. \n"
367 	       "	       Use default machine.\n"));
368 	}
369     }
370 
371   return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
372 }
373 
374 /* The final processing done just before writing out an ARC ELF object file.
375    This gets the ARC architecture right based on the machine number.  */
376 
377 static void
378 arc_elf_final_write_processing (bfd * abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
379 {
380   unsigned long val;
381   unsigned long emf;
382 
383   switch (bfd_get_mach (abfd))
384     {
385     case bfd_mach_arc_arc600:
386       val = E_ARC_MACH_ARC600;
387       emf = EM_ARC_COMPACT;
388       break;
389     case bfd_mach_arc_arc601:
390       val = E_ARC_MACH_ARC601;
391       emf = EM_ARC_COMPACT;
392       break;
393     case bfd_mach_arc_arc700:
394       val = E_ARC_MACH_ARC700;
395       emf = EM_ARC_COMPACT;
396       break;
397     case bfd_mach_arc_arcv2:
398       val = EF_ARC_CPU_GENERIC;
399       emf = EM_ARC_COMPACT2;
400       /* TODO: Check validity of this.  It can also be ARCV2EM here.
401 	 Previous version sets the e_machine here.  */
402       break;
403     default:
404       abort ();
405     }
406   elf_elfheader (abfd)->e_flags &= ~EF_ARC_MACH;
407   elf_elfheader (abfd)->e_flags |= val;
408   elf_elfheader (abfd)->e_machine = emf;
409 
410   /* Record whatever is the current syscall ABI version.  */
411   elf_elfheader (abfd)->e_flags |= E_ARC_OSABI_CURRENT;
412 }
413 
414 #define BFD_DEBUG_PIC(...)
415 
416 struct arc_relocation_data
417 {
418   bfd_vma	  reloc_offset;
419   bfd_vma	  reloc_addend;
420   bfd_vma	  got_offset_value;
421 
422   bfd_vma	  sym_value;
423   asection *	  sym_section;
424 
425   reloc_howto_type *howto;
426 
427   asection *	  input_section;
428 
429   bfd_vma	  sdata_begin_symbol_vma;
430   bfd_boolean	  sdata_begin_symbol_vma_set;
431   bfd_vma	  got_symbol_vma;
432 
433   bfd_boolean	  should_relocate;
434 };
435 
436 static void
437 debug_arc_reloc (struct arc_relocation_data reloc_data)
438 {
439   fprintf (stderr, "Reloc type=%s, should_relocate = %s\n",
440 	   reloc_data.howto->name,
441 	   reloc_data.should_relocate ? "true" : "false");
442   fprintf (stderr, "  offset = 0x%x, addend = 0x%x\n",
443 	   (unsigned int) reloc_data.reloc_offset,
444 	   (unsigned int) reloc_data.reloc_addend);
445   fprintf (stderr, " Symbol:\n");
446   fprintf (stderr, "  value = 0x%08x\n",
447 	   (unsigned int) reloc_data.sym_value);
448   if (reloc_data.sym_section != NULL)
449     {
450       fprintf (stderr, "IN IF\n");
451       fprintf (stderr,
452 	       "  section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n",
453 	       reloc_data.sym_section->name,
454 	       (unsigned int) reloc_data.sym_section->output_offset,
455 	       (unsigned int) reloc_data.sym_section->output_section->vma);
456     }
457   else
458     fprintf (stderr, "	symbol section is NULL\n");
459 
460   fprintf (stderr, " Input_section:\n");
461   if (reloc_data.input_section != NULL)
462     {
463       fprintf (stderr,
464 	       "  section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n",
465 	       reloc_data.input_section->name,
466 	       (unsigned int) reloc_data.input_section->output_offset,
467 	       (unsigned int) reloc_data.input_section->output_section->vma);
468       fprintf (stderr, "  changed_address = 0x%08x\n",
469 	       (unsigned int) (reloc_data.input_section->output_section->vma +
470 	       reloc_data.input_section->output_offset +
471 	       reloc_data.reloc_offset));
472     }
473   else
474     fprintf (stderr, "	input section is NULL\n");
475 }
476 
477 static ATTRIBUTE_UNUSED bfd_vma
478 get_middle_endian_relocation (bfd_vma reloc)
479 {
480   bfd_vma ret =
481 	      ((reloc & 0xffff0000) >> 16) |
482 	      ((reloc & 0xffff) << 16);
483   return ret;
484 }
485 
486 #define ME(RELOC) (get_middle_endian_reloction(RELOC))
487 
488 #define S (reloc_data.sym_value \
489 	   + reloc_data.sym_section->output_offset \
490 	   + reloc_data.sym_section->output_section->vma)
491 #define A (reloc_data.reloc_addend)
492 #define B (0)
493 #define G (reloc_data.got_offset_value)
494 #define GOT (reloc_data.got_symbol_vma + 12)
495 #define L (reloc_data.sym_value \
496 	   + reloc_data.sym_section->output_section->vma \
497 	   + reloc_data.sym_section->output_offset)
498 #define MES (0)
499 	/* P: relative offset to PCL The offset should be to the current location
500 	   aligned to 32 bits.  */
501 #define P ( \
502 	    (reloc_data.input_section->output_section->vma \
503 	     + reloc_data.input_section->output_offset \
504 	     + (reloc_data.reloc_offset - (bitsize >= 32 ? 4 : 0)) \
505 	    ) & ~0x3)
506 #define PDATA ( \
507 	    (reloc_data.input_section->output_section->vma \
508 	     + reloc_data.input_section->output_offset \
509 	     + (reloc_data.reloc_offset) \
510 	    ) & ~0x3)
511 #define SECTSTAR (reloc_data.input_section->output_offset)
512 #define SECTSTART (reloc_data.input_section->output_offset)
513 #define _SDA_BASE_ (reloc_data.sdata_begin_symbol_vma)
514 
515 #define none (0)
516 
517 #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
518   case R_##TYPE: \
519     { \
520       bfd_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \
521       relocation = FORMULA  ; \
522       insn = RELOC_FUNCTION (insn, relocation); \
523     } \
524     break;
525 
526 static bfd_reloc_status_type
527 arc_do_relocation (bfd_byte * contents, struct arc_relocation_data reloc_data)
528 {
529   bfd_vma relocation = 0;
530   bfd_vma insn;
531   bfd_vma orig_insn ATTRIBUTE_UNUSED;
532 
533   if (reloc_data.should_relocate == FALSE)
534     return bfd_reloc_notsupported;
535 
536   switch (reloc_data.howto->size)
537     {
538       case 2:
539 	insn = arc_bfd_get_32 (reloc_data.input_section->owner,
540 			       contents + reloc_data.reloc_offset,
541 			       reloc_data.input_section);
542 	break;
543       case 1:
544       case 0:
545 	insn = arc_bfd_get_16 (reloc_data.input_section->owner,
546 			       contents + reloc_data.reloc_offset,
547 			       reloc_data.input_section);
548 	break;
549       default:
550 	insn = 0;
551 	BFD_ASSERT (0);
552 	break;
553     }
554 
555   orig_insn = insn;
556 
557   switch (reloc_data.howto->type)
558     {
559       #include "elf/arc-reloc.def"
560 
561       default:
562 	BFD_ASSERT (0);
563 	break;
564     }
565 
566   /* Check for relocation overflow.  */
567   if (reloc_data.howto->complain_on_overflow != complain_overflow_dont)
568     {
569       bfd_reloc_status_type flag;
570       flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow,
571 				 reloc_data.howto->bitsize,
572 				 reloc_data.howto->rightshift,
573 				 bfd_arch_bits_per_address (reloc_data.input_section->owner),
574 				 relocation);
575 
576 #undef DEBUG_ARC_RELOC
577 #define DEBUG_ARC_RELOC(A) debug_arc_reloc (A)
578       if (flag != bfd_reloc_ok)
579 	{
580 	  fprintf (stderr, "Relocation overflows !!!!\n");
581 
582 	  DEBUG_ARC_RELOC (reloc_data);
583 
584 	  fprintf (stderr,
585 		  "Relocation value = signed -> %d, unsigned -> %u, hex -> (0x%08x)\n",
586 		  (int) relocation,
587 		  (unsigned int) relocation,
588 		  (unsigned int) relocation);
589 	  return flag;
590 	}
591     }
592 #undef DEBUG_ARC_RELOC
593 #define DEBUG_ARC_RELOC(A)
594 
595   switch (reloc_data.howto->size)
596     {
597       case 2:
598 	arc_bfd_put_32 (reloc_data.input_section->owner, insn,
599 		       contents + reloc_data.reloc_offset,
600 		       reloc_data.input_section);
601 	break;
602       case 1:
603       case 0:
604 	arc_bfd_put_16 (reloc_data.input_section->owner, insn,
605 		       contents + reloc_data.reloc_offset,
606 		       reloc_data.input_section);
607 	break;
608       default:
609 	ARC_DEBUG ("size = %d\n", reloc_data.howto->size);
610 	BFD_ASSERT (0);
611 	break;
612     }
613 
614   return bfd_reloc_ok;
615 }
616 #undef S
617 #undef A
618 #undef B
619 #undef G
620 #undef GOT
621 #undef L
622 #undef MES
623 #undef P
624 #undef SECTSTAR
625 #undef SECTSTART
626 #undef _SDA_BASE_
627 #undef none
628 
629 #undef ARC_RELOC_HOWTO
630 
631 static bfd_vma *
632 arc_get_local_got_offsets (bfd * abfd)
633 {
634   static bfd_vma *local_got_offsets = NULL;
635 
636   if (local_got_offsets == NULL)
637     {
638       size_t	   size;
639       unsigned int i;
640       Elf_Internal_Shdr *symtab_hdr = &((elf_tdata (abfd))->symtab_hdr);
641 
642       size = symtab_hdr->sh_info * sizeof (bfd_vma);
643       local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
644       if (local_got_offsets == NULL)
645 	return FALSE;
646       elf_local_got_offsets (abfd) = local_got_offsets;
647       for (i = 0; i < symtab_hdr->sh_info; i++)
648 	local_got_offsets[i] = (bfd_vma) - 1;
649     }
650 
651   return local_got_offsets;
652 }
653 
654 
655 /* Relocate an arc ELF section.
656    Function : elf_arc_relocate_section
657    Brief    : Relocate an arc section, by handling all the relocations
658   	     appearing in that section.
659    Args     : output_bfd    : The bfd being written to.
660   	      info	    : Link information.
661   	      input_bfd     : The input bfd.
662   	      input_section : The section being relocated.
663   	      contents	    : contents of the section being relocated.
664   	      relocs	    : List of relocations in the section.
665   	      local_syms    : is a pointer to the swapped in local symbols.
666   	      local_section : is an array giving the section in the input file
667   			      corresponding to the st_shndx field of each
668   			      local symbol.  */
669 static bfd_boolean
670 elf_arc_relocate_section (bfd *                   output_bfd,
671 			  struct bfd_link_info *  info,
672 			  bfd *                   input_bfd,
673 			  asection *              input_section,
674 			  bfd_byte *              contents,
675 			  Elf_Internal_Rela *     relocs,
676 			  Elf_Internal_Sym *      local_syms,
677 			  asection **             local_sections)
678 {
679   Elf_Internal_Shdr *           symtab_hdr;
680   struct elf_link_hash_entry ** sym_hashes;
681   bfd_vma *                     local_got_offsets;
682   Elf_Internal_Rela *           rel;
683   Elf_Internal_Rela *           relend;
684 
685   symtab_hdr = &((elf_tdata (input_bfd))->symtab_hdr);
686   sym_hashes = elf_sym_hashes (input_bfd);
687 
688   rel = relocs;
689   relend = relocs + input_section->reloc_count;
690   for (; rel < relend; rel++)
691     {
692       enum elf_arc_reloc_type       r_type;
693       reloc_howto_type *            howto;
694       unsigned long                 r_symndx;
695       struct elf_link_hash_entry *  h;
696       Elf_Internal_Sym *            sym;
697       asection *                    sec;
698 
699       struct arc_relocation_data reloc_data =
700       {
701 	.reloc_offset = 0,	/* bfd_vma reloc_offset; */
702 	.reloc_addend = 0,	/* bfd_vma reloc_addend; */
703 	.got_offset_value = 0,	/* bfd_vma got_offset_value; */
704 	.sym_value = 0,		/* bfd_vma sym_value; */
705 	.sym_section = NULL,	/* asection *sym_section; */
706 	.howto = NULL,		/* reloc_howto_type *howto; */
707 	.input_section = NULL,	/* asection *input_section; */
708 	.sdata_begin_symbol_vma = 0,	/* bfd_vma sdata_begin_symbol_vma; */
709 	.sdata_begin_symbol_vma_set = FALSE,	/* bfd_vma sdata_begin_symbol_vma_set; */
710 	.got_symbol_vma = 0,	/* bfd_vma got_symbol_vma; */
711 	.should_relocate = FALSE	/* bfd_boolean should_relocate; */
712       };
713 
714       struct elf_link_hash_entry *h2;
715 
716       h2 = elf_link_hash_lookup (elf_hash_table (info), "__SDATA_BEGIN__",
717 				 FALSE, FALSE, TRUE);
718 
719       if (reloc_data.sdata_begin_symbol_vma_set == FALSE
720 	    && h2 != NULL && h2->root.type != bfd_link_hash_undefined)
721 	{
722 	  reloc_data.sdata_begin_symbol_vma =
723 	    (h2->root.u.def.value +
724 	     h2->root.u.def.section->output_section->vma);
725 	  reloc_data.sdata_begin_symbol_vma_set = TRUE;
726 	}
727 
728       h2 = elf_link_hash_lookup (elf_hash_table (info),
729 				 "_GLOBAL_OFFSET_TABLE_", FALSE, FALSE,
730 				 TRUE);
731       if (h2 != NULL && h2->root.type != bfd_link_hash_undefined)
732 	{
733 	  reloc_data.got_symbol_vma =
734 	      (h2->root.u.def.value +
735 	       h2->root.u.def.section->output_section->vma);
736 	}
737 
738       r_type = ELF32_R_TYPE (rel->r_info);
739 
740       if (r_type >= (int) R_ARC_max)
741 	{
742 	  bfd_set_error (bfd_error_bad_value);
743 	  return FALSE;
744 	}
745       howto = &elf_arc_howto_table[r_type];
746 
747       reloc_data.input_section = input_section;
748       reloc_data.howto = howto;
749       reloc_data.reloc_offset = rel->r_offset;
750       reloc_data.reloc_addend = rel->r_addend;
751 
752       r_symndx = ELF32_R_SYM (rel->r_info);
753 
754       /* This is a final link.  */
755       h = NULL;
756       sym = NULL;
757       sec = NULL;
758 
759       if (r_symndx < symtab_hdr->sh_info) /* A local symbol.  */
760 	{
761 	  sym = local_syms + r_symndx;
762 	  sec = local_sections[r_symndx];
763 
764 	  reloc_data.sym_value = sym->st_value;
765 	  reloc_data.sym_section = sec;
766 
767 	    if (is_reloc_for_GOT (reloc_data.howto))
768 	      {
769 		local_got_offsets = arc_get_local_got_offsets (output_bfd);
770 		reloc_data.got_offset_value = local_got_offsets[r_symndx];
771 	      }
772 
773 	  reloc_data.should_relocate = TRUE;
774 	}
775       else /* Global symbol.  */
776 	{
777 	  /* Get the symbol's entry in the symtab.  */
778 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
779 
780 	  while (h->root.type == bfd_link_hash_indirect
781 		 || h->root.type == bfd_link_hash_warning)
782 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
783 
784 	  BFD_ASSERT ((h->dynindx == -1) >= (h->forced_local != 0));
785 	  /* If we have encountered a definition for this symbol.  */
786 	  if (h->root.type == bfd_link_hash_defined
787 	      || h->root.type == bfd_link_hash_defweak)
788 	    {
789 	      reloc_data.sym_value = h->root.u.def.value;
790 	      reloc_data.sym_section = h->root.u.def.section;
791 
792 	      reloc_data.should_relocate = TRUE;
793 
794 	      if (is_reloc_for_GOT (howto))
795 		{
796 		  struct dynamic_sections ds =
797 		  arc_create_dynamic_sections (output_bfd, info);
798 
799 		  /* TODO: Change it to use arc_do_relocation with ARC_32
800 		     reloc.  */
801 		  bfd_vma relocation =
802 		    reloc_data.sym_value + reloc_data.reloc_addend
803 		    + reloc_data.sym_section->output_offset
804 		    + reloc_data.sym_section->output_section->vma;
805 
806 		  bfd_put_32 (output_bfd, relocation, ds.sgot->contents + h->got.offset);
807 
808 		}
809 	    }
810 	  else if (h->root.type == bfd_link_hash_undefweak)
811 	    {
812 	      /* Is weak symbol and has no definition.  */
813 	      continue;
814 	    }
815 	  else
816 	    {
817 	      if (is_reloc_for_GOT (howto))
818 		{
819 		  struct dynamic_sections ds =
820 		      arc_create_dynamic_sections (output_bfd, info);
821 
822 		  reloc_data.sym_value = h->root.u.def.value;
823 		  reloc_data.sym_section = ds.sgot;
824 
825 		  reloc_data.should_relocate = TRUE;
826 		}
827 	      else if (is_reloc_for_PLT (howto))
828 		{
829 		  struct dynamic_sections ds =
830 		    arc_create_dynamic_sections (output_bfd, info);
831 
832 		  reloc_data.sym_value = h->plt.offset;
833 		  reloc_data.sym_section = ds.splt;
834 
835 		  reloc_data.should_relocate = TRUE;
836 		}
837 	      else if (!(*info->callbacks->undefined_symbol)
838 		       (info, h->root.root.string, input_bfd, input_section,
839 			rel->r_offset,!bfd_link_pic (info)))
840 		{
841 		  return FALSE;
842 		}
843 	    }
844 
845 	  reloc_data.got_offset_value = h->got.offset;
846 	}
847 
848       if (is_reloc_SDA_relative (howto) && reloc_data.sdata_begin_symbol_vma_set == FALSE)
849 	{
850 	  (*_bfd_error_handler)
851 	      ("Error: Linker symbol __SDATA_BEGIN__ not found");
852 	  bfd_set_error (bfd_error_bad_value);
853 	  return FALSE;
854 	}
855 
856       DEBUG_ARC_RELOC (reloc_data);
857       if (arc_do_relocation (contents, reloc_data) != bfd_reloc_ok)
858 	return FALSE;
859     }
860 
861   return TRUE;
862 }
863 
864 static struct dynamic_sections
865 arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info)
866 {
867   static bfd * dynobj = NULL;
868   struct dynamic_sections ds =
869   {
870 	.initialized = FALSE,
871 	.sgot = NULL,
872 	.srelgot = NULL,
873 	.sgotplt = NULL,
874 	.sdyn = NULL,
875 	.splt = NULL,
876 	.srelplt = NULL
877   };
878 
879   if (dynobj == NULL)
880     {
881       elf_hash_table (info)->dynobj = dynobj = abfd;
882       if (!_bfd_elf_create_got_section (dynobj, info))
883 	return ds;
884     }
885   else
886     dynobj = (elf_hash_table (info))->dynobj;
887 
888   ds.sgot = bfd_get_section_by_name (dynobj, ".got");
889 
890   ds.srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
891   if (ds.srelgot == NULL)
892     {
893       ds.srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
894 					 SEC_ALLOC
895 					 | SEC_LOAD
896 					 | SEC_HAS_CONTENTS
897 					 | SEC_IN_MEMORY
898 					 | SEC_LINKER_CREATED
899 					 | SEC_READONLY);
900       if (ds.srelgot == NULL
901 	  || !bfd_set_section_alignment (dynobj, ds.srelgot, 2))
902 	return ds;
903     }
904 
905   ds.sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
906 
907   ds.sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
908   ds.splt = bfd_get_section_by_name (dynobj, ".plt");
909   ds.srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
910 
911   ds.initialized = TRUE;
912 
913   return ds;
914 }
915 
916 #define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
917   ds.s##SECNAME->size; \
918   { \
919     if (COND_FOR_RELOC) ds.srel##SECNAME->size += sizeof (Elf32_External_Rela); \
920     if (H)  \
921       if (h->dynindx == -1 && !h->forced_local) \
922 	if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
923 	  return FALSE; \
924     ds.s##SECNAME->size += 4; \
925   }
926 
927 static bfd_boolean
928 elf_arc_check_relocs (bfd *                      abfd,
929 		      struct bfd_link_info *     info,
930 		      asection *                 sec,
931 		      const Elf_Internal_Rela *  relocs)
932 {
933   Elf_Internal_Shdr *            symtab_hdr;
934   struct elf_link_hash_entry **  sym_hashes;
935   bfd_vma *                      local_got_offsets;
936   const Elf_Internal_Rela *      rel;
937   const Elf_Internal_Rela *      rel_end;
938   bfd *                          dynobj ATTRIBUTE_UNUSED;
939 
940   dynobj = (elf_hash_table (info))->dynobj;
941   symtab_hdr = &((elf_tdata (abfd))->symtab_hdr);
942   sym_hashes = elf_sym_hashes (abfd);
943   local_got_offsets = arc_get_local_got_offsets (abfd);
944 
945   struct dynamic_sections ds = arc_create_dynamic_sections (abfd, info);
946 
947   rel_end = relocs + sec->reloc_count;
948   for (rel = relocs; rel < rel_end; rel++)
949     {
950       enum elf_arc_reloc_type r_type;
951       reloc_howto_type *howto;
952       unsigned long   r_symndx;
953       struct elf_link_hash_entry *h;
954 
955       r_type = ELF32_R_TYPE (rel->r_info);
956 
957       if (r_type >= (int) R_ARC_max)
958 	{
959 	  bfd_set_error (bfd_error_bad_value);
960 	  return FALSE;
961 	}
962       howto = &elf_arc_howto_table[r_type];
963 
964       /* Load symbol information.  */
965       r_symndx = ELF32_R_SYM (rel->r_info);
966       if (r_symndx < symtab_hdr->sh_info) /* Is a local symbol.  */
967 	h = NULL;
968       else /* Global one.  */
969 	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
970 
971       if (is_reloc_for_PLT (howto) == TRUE)
972 	{
973 	  if (h == NULL)
974 	    continue;
975 	  else
976 	    h->needs_plt = 1;
977 	}
978 
979       if (is_reloc_for_GOT (howto) == TRUE)
980 	{
981 	  if (h == NULL)
982 	    {
983 	      /* Local symbol.  */
984 	      local_got_offsets[r_symndx] =
985 		ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info), NULL);
986 	    }
987 	  else
988 	    {
989 	      /* Global symbol.  */
990 	      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
991 	      h->got.offset =
992 		ADD_SYMBOL_REF_SEC_AND_RELOC (got, TRUE, h);
993 	    }
994 	}
995     }
996 
997   return TRUE;
998 }
999 
1000 #define ELF_DYNAMIC_INTERPRETER  "/sbin/ld-uClibc.so"
1001 
1002 /* Size of one plt entry in bytes.  */
1003 #define PLT_ENTRY_SIZE	12
1004 #define PLT_ENTRY_SIZE_V2 16
1005 
1006 /* Instructions appear in memory as a sequence of half-words (16 bit);
1007    individual half-words are represented on the target in target byte order.
1008    We use 'unsigned short' on the host to represent the PLT templates,
1009    and translate to target byte order as we copy to the target.  */
1010 typedef unsigned short insn_hword;
1011 
1012 
1013 /* TODO: Make this PLT entry code be in a separate object file.  */
1014 /* TODO: This is a linker BTW, we should be able to link. :)  */
1015 
1016 /* The zeroth entry in the absolute plt entry.  */
1017 static const insn_hword elf_arc_abs_plt0_entry[2 * PLT_ENTRY_SIZE / 2] =
1018 {
1019   0x1600,	/* ld %r11, [0] */
1020   0x700b,
1021   0x0000,
1022   0x0000,
1023   0x1600,	/* ld %r10, [0] */
1024   0x700a,	/* */
1025   0,
1026   0,
1027   0x2020,	/* j [%r10] */
1028   0x0280,	/* ---"---- */
1029   0x0000,	/* pad */
1030   0x0000	/* pad */
1031 };
1032 
1033 /* Contents of the subsequent entries in the absolute plt.  */
1034 static const insn_hword elf_arc_abs_pltn_entry[PLT_ENTRY_SIZE / 2] =
1035 {
1036   0x2730,	/* ld %r12, [%pc,func@gotpc] */
1037   0x7f8c,	/* ------ " " -------------- */
1038   0x0000,	/* ------ " " -------------- */
1039   0x0000,	/* ------ " " -------------- */
1040   0x7c20,	/* j_s.d [%r12] */
1041   0x74ef	/* mov_s %r12, %pcl */
1042 };
1043 
1044 /* The zeroth entry in the absolute plt entry for ARCv2.  */
1045 static const insn_hword elf_arcV2_abs_plt0_entry[2 * PLT_ENTRY_SIZE_V2 / 2] =
1046 {
1047   0x1600, 0x700b, 0, 0,   /* ld %r11, [0] */
1048   0x1600, 0x700a, 0, 0,   /* ld %r10, [0] */
1049   0x2020, 0x0280,	  /* j [%r10] */
1050   0x0000, 0x0000,	  /* -> RELOCATED TO ABS ADDRESS OF GOT <- */
1051   0x0000,		  /* pad */
1052   0x0000,		  /* pad */
1053   0x0000,		  /* pad */
1054   0x0000		  /* pad */
1055 };
1056 
1057 /* Contents of the subsequent entries in the absolute plt for ARCv2.  */
1058 static const insn_hword elf_arcV2_abs_pltn_entry[PLT_ENTRY_SIZE_V2 / 2] =
1059 {
1060   0x2730,	/* ld %r12, [%pcl,func@gotpc] */
1061   0x7f8c,	/* ------ " " -------------- */
1062   0x0000,	/* ------ " " -------------- */
1063   0x0000,	/* ------ " " -------------- */
1064   0x2021,	/* j.d [%r12] */
1065   0x0300,	/* ------ " " -------------- */
1066   0x240a,	/* mov %r12, %pcl */
1067   0x1fc0	/* ------ " " -------------- */
1068 };
1069 
1070 /* The zeroth entry in the pic plt entry.  */
1071 static const insn_hword elf_arc_pic_plt0_entry[2 * PLT_ENTRY_SIZE / 2] =
1072 {
1073   0x2730,	/* ld %r11, [pcl,0] : 0 to be replaced by
1074 		   _DYNAMIC@GOTPC+4 */
1075   0x7f8b,
1076   0x0000,
1077   0x0000,
1078   0x2730,	/* ld %r10, [pcl,0] : 0 to be replaced by
1079 		   -DYNAMIC@GOTPC+8 */
1080   0x7f8a,	/* */
1081   0,
1082   0,
1083   0x2020,	/* j [%r10] */
1084   0x0280,	/* ---"---- */
1085   0x0000,	/* pad */
1086   0x0000	/* pad */
1087 };
1088 
1089 /* Contents of the subsequent entries in the pic plt.  */
1090 static const insn_hword elf_arc_pic_pltn_entry[PLT_ENTRY_SIZE / 2] =
1091 {
1092   0x2730,	/* ld %r12, [%pc,func@got] */
1093   0x7f8c,	/* ------ " " -------------- */
1094   0x0000,	/* ------ " " -------------- */
1095   0x0000,	/* ------ " " -------------- */
1096   0x7c20,	/* j_s.d [%r12] */
1097   0x74ef,	/* mov_s %r12, %pcl */
1098 };
1099 
1100 /* The zeroth entry in the pic plt entry for ARCv2.  */
1101 static const insn_hword elf_arcV2_pic_plt0_entry[2 * PLT_ENTRY_SIZE_V2 / 2] =
1102 {
1103   0x2730,	/* ld %r11, [pcl,0] : 0 to be replaced by
1104 		   _DYNAMIC@GOTPC+4 */
1105   0x7f8b,
1106   0x0000,
1107   0x0000,
1108   0x2730,	/* ld %r10, [pcl,0] : 0 to be replaced by
1109 		   -DYNAMIC@GOTPC+8 */
1110   0x7f8a,	/* */
1111   0,
1112   0,
1113   0x2020,	/* j [%r10] */
1114   0x0280,	/* ---"---- */
1115   0x0000,	/* pad */
1116   0x0000,	/* pad */
1117   0x0000,	/* pad */
1118   0x0000,	/* pad */
1119   0x0000,	/* pad */
1120   0x0000	/* pad */
1121 };
1122 
1123 #define elf_arcV2_pic_PLT0_ENTRY_SIZE (2 * PLT_ENTRY_SIZE_V2/2)
1124 
1125 /* Contents of the subsequent entries in the pic plt for ARCv2.  */
1126 static const insn_hword elf_arcV2_pic_pltn_entry[PLT_ENTRY_SIZE_V2 / 2] =
1127 {
1128   0x2730,	/* ld %r12, [%pc,func@got] */
1129   0x7f8c,	/* ------ " " -------------- */
1130   0x0000,	/* ------ " " -------------- */
1131   0x0000,	/* ------ " " -------------- */
1132   0x2021,	/* j.d [%r12] */
1133   0x0300,	/* ------ " " -------------- */
1134   0x240a,	/* mov %r12, %pcl */
1135   0x1fc0	/* ------ " " -------------- */
1136 };
1137 
1138 #define elf_arcV2_pic_PLTN_ENTRY_SIZE (PLT_ENTRY_SIZE_V2/2)
1139 
1140 enum plt_reloc_symbol
1141 {
1142   LAST_RELOC = 0,
1143 
1144   SGOT = 1,
1145 
1146   RELATIVE = (1 << 8),
1147   MIDDLE_ENDIAN = (1 << 9)
1148 };
1149 
1150 #define IS_RELATIVE(S) ((S & RELATIVE) != 0)
1151 #define IS_MIDDLE_ENDIAN(S) ((S & MIDDLE_ENDIAN) != 0)
1152 #define SYM_ONLY(S) (S & 0xFF)
1153 
1154 struct plt_reloc
1155 {
1156   bfd_vma	  offset;
1157   bfd_vma	  size;
1158   bfd_vma	  mask;
1159   enum plt_reloc_symbol symbol;
1160   bfd_vma	  addend;
1161 };
1162 
1163 struct plt_version_t
1164 {
1165   const insn_hword *    entry;
1166   const bfd_vma		entry_size;
1167   const insn_hword *    elem;
1168   const bfd_vma		elem_size;
1169 
1170   struct plt_reloc entry_relocs[5];
1171   struct plt_reloc elem_relocs[5];
1172 };
1173 
1174 
1175 #define PLT_DATA(NAME, ...) \
1176   .entry = NAME##_plt0_entry, \
1177   .entry_size = NAME##_PLT0_ENTRY_SIZE, \
1178   .elem = NAME##_pltn_entry, \
1179   .elem_size = NAME##_PLTN_ENTRY_SIZE
1180 
1181 struct plt_version_t plt_versions[] =
1182 {
1183   {
1184     PLT_DATA (elf_arcV2_pic),
1185     .entry_relocs =
1186     {
1187       {4, 32, 0xFFFFFFFF, SGOT | RELATIVE | MIDDLE_ENDIAN, 4},
1188       {12, 32, 0xFFFFFFFF, SGOT | RELATIVE | MIDDLE_ENDIAN, 8},
1189       {20, 32, 0xFFFFFFFF, SGOT, 0},
1190       {0, 0, 0, LAST_RELOC, 0}
1191     },
1192     .elem_relocs =
1193     {
1194       {4, 32, 0xFFFFFFFF, SGOT, 0},
1195       {0, 0, 0, LAST_RELOC, 0}
1196     }
1197   }
1198 };
1199 #undef PLT_DATA
1200 
1201 static struct plt_version_t *
1202 arc_get_plt_version (void)
1203 {
1204   return &(plt_versions[0]);
1205 }
1206 
1207 static bfd_vma
1208 add_symbol_to_plt (struct bfd_link_info *info)
1209 {
1210   bfd *dynobj = (elf_hash_table (info))->dynobj;
1211   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
1212   bfd_vma ret;
1213 
1214   /* If this is the first .plt entry, make room for the special first entry.  */
1215   if (ds.splt->size == 0)
1216     ds.splt->size += 2 *
1217 		     (bfd_get_mach (dynobj) == bfd_mach_arc_arcv2
1218 		      ? PLT_ENTRY_SIZE_V2 : PLT_ENTRY_SIZE);
1219 
1220   ret = ds.splt->size;
1221 
1222   ds.splt->size += (bfd_get_mach (dynobj) == bfd_mach_arc_arcv2
1223 		    ? PLT_ENTRY_SIZE_V2
1224 		    : PLT_ENTRY_SIZE
1225 		   );
1226   ds.sgotplt->size += 4;
1227   ds.srelplt->size += sizeof (Elf32_External_Rela);
1228 
1229   return ret;
1230 }
1231 
1232 #define PLT_DO_RELOCS_FOR_ENTRY(DS, RELOCS) \
1233   plt_do_relocs_for_symbol (DS, RELOCS, 0, 0)
1234 
1235 static void
1236 plt_do_relocs_for_symbol (struct dynamic_sections *ds,
1237 			  struct plt_reloc *reloc,
1238 			  bfd_vma plt_offset,
1239 			  bfd_vma symbol_got_offset)
1240 {
1241   while (SYM_ONLY (reloc->symbol) != LAST_RELOC)
1242     {
1243       bfd_vma relocation = 0;
1244 
1245       switch (SYM_ONLY (reloc->symbol))
1246 	{
1247 	  case SGOT:
1248 		relocation =
1249 		    ds->sgotplt->output_section->vma +
1250 		    ds->sgotplt->output_offset + symbol_got_offset;
1251 		break;
1252 	}
1253       relocation += reloc->addend;
1254 
1255       relocation -= (IS_RELATIVE (reloc->symbol))
1256 	  ? ds->splt->output_section->vma + ds->splt->output_offset +
1257 	  plt_offset + reloc->offset : 0;
1258 
1259       if (IS_MIDDLE_ENDIAN (reloc->symbol))
1260 	{
1261 	  relocation =
1262 	      ((relocation & 0xffff0000) >> 16) |
1263 	      ((relocation & 0xffff) << 16);
1264 	}
1265 
1266       switch (reloc->size)
1267 	{
1268 	  case 32:
1269 	    bfd_put_32 (ds->splt->output_section->owner,
1270 			relocation,
1271 			ds->splt->contents + plt_offset + reloc->offset);
1272 	    break;
1273 	}
1274 
1275       reloc = &(reloc[1]);	/* Jump to next relocation.  */
1276     }
1277 }
1278 
1279 static void
1280 relocate_plt_for_symbol (struct bfd_link_info *info,
1281 			 struct elf_link_hash_entry *h)
1282 {
1283   bfd * dynobj = elf_hash_table (info)->dynobj;
1284   struct plt_version_t *plt_data = arc_get_plt_version ();
1285   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
1286 
1287   bfd_vma plt_index = h->plt.offset / plt_data->elem_size;
1288   bfd_vma got_offset = (plt_index + 3) * 4;
1289 
1290   memcpy (ds.splt->contents + h->plt.offset, plt_data->elem,
1291 	  plt_data->elem_size * sizeof (insn_hword));
1292   plt_do_relocs_for_symbol (&ds, plt_data->elem_relocs, h->plt.offset,
1293 			    got_offset);
1294 }
1295 
1296 static void
1297 relocate_plt_for_entry (struct bfd_link_info *info)
1298 {
1299   bfd * dynobj = (elf_hash_table (info))->dynobj;
1300   struct plt_version_t *plt_data = arc_get_plt_version ();
1301   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
1302 
1303   memcpy (ds.splt->contents, plt_data->entry,
1304 	  plt_data->entry_size * sizeof (insn_hword));
1305   PLT_DO_RELOCS_FOR_ENTRY (&ds, plt_data->entry_relocs);
1306 }
1307 
1308 
1309 /* Desc : Adjust a symbol defined by a dynamic object and referenced by a
1310    regular object.  The current definition is in some section of the
1311    dynamic object, but we're not including those sections.  We have to
1312    change the definition to something the rest of the link can
1313    understand.  */
1314 
1315 static bfd_boolean
1316 elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info,
1317 			      struct elf_link_hash_entry *h)
1318 {
1319   bfd *dynobj = (elf_hash_table (info))->dynobj;
1320   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
1321 
1322   if (h->needs_plt == 1)
1323     {
1324       if (!bfd_link_pic (info) && !h->def_dynamic && !h->ref_dynamic)
1325 	{
1326 	  /* This case can occur if we saw a PLT32 reloc in an input
1327 	     file, but the symbol was never referred to by a dynamic
1328 	     object.  In such a case, we don't actually need to build
1329 	     a procedure linkage table, and we can just do a PC32
1330 	     reloc instead.  */
1331 	  BFD_ASSERT (h->needs_plt);
1332 	  return TRUE;
1333 	}
1334 
1335       /* Make sure this symbol is output as a dynamic symbol.  */
1336       if (h->dynindx == -1 && !h->forced_local
1337 	  && !bfd_elf_link_record_dynamic_symbol (info, h))
1338 	return FALSE;
1339 
1340       if (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
1341 	{
1342 	  bfd_vma loc = add_symbol_to_plt (info);
1343 
1344 	  if (!bfd_link_pic (info) && !h->def_regular)
1345 	    {
1346 	      h->root.u.def.section = ds.splt;
1347 	      h->root.u.def.value = loc;
1348 	    }
1349 	  h->plt.offset = loc;
1350 	}
1351     }
1352   else
1353     {
1354       h->plt.offset = (bfd_vma) - 1;
1355       h->needs_plt = 0;
1356     }
1357 
1358   return TRUE;
1359 }
1360 
1361 #define ADD_RELA(BFD, SECTION, OFFSET, SYM_IDX, TYPE, ADDEND) \
1362 {\
1363   struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info); \
1364   bfd_byte * rloc = ds.srel##SECTION->contents + \
1365     ((ds.srel##SECTION->reloc_count++) * sizeof (Elf32_External_Rela)); \
1366   Elf_Internal_Rela rel; \
1367   bfd_put_32 (output_bfd, (bfd_vma) 0, ds.s##SECTION->contents + OFFSET); \
1368   rel.r_addend = ADDEND; \
1369   rel.r_offset = (ds.s##SECTION)->output_section->vma + (ds.s##SECTION)->output_offset + OFFSET; \
1370   rel.r_info = ELF32_R_INFO (SYM_IDX, TYPE); \
1371   bfd_elf32_swap_reloca_out (BFD, &rel, rloc); \
1372 }
1373 
1374 /* Function :  elf_arc_finish_dynamic_symbol
1375    Brief    :  Finish up dynamic symbol handling.  We set the
1376   	     contents of various dynamic sections here.
1377    Args     :  output_bfd :
1378   	       info	  :
1379   	       h	  :
1380   	       sym	  :
1381    Returns  : True/False as the return status.  */
1382 static bfd_boolean
1383 elf_arc_finish_dynamic_symbol (bfd * output_bfd,
1384 			       struct bfd_link_info *info,
1385 			       struct elf_link_hash_entry *h,
1386 			       Elf_Internal_Sym * sym)
1387 {
1388   if (h->plt.offset != (bfd_vma) - 1)
1389     relocate_plt_for_symbol (info, h);
1390 
1391   if (h->got.offset != (bfd_vma) - 1)
1392     {
1393       if (bfd_link_pic (info) && (info->symbolic || h->dynindx == -1)
1394 	  && h->def_regular)
1395 	{
1396 	  ADD_RELA (output_bfd, got, h->got.offset, 0, R_ARC_RELATIVE, 0);
1397 	}
1398       else
1399 	{
1400 	  ADD_RELA (output_bfd, got, h->got.offset, h->dynindx,
1401 		    R_ARC_GLOB_DAT, 0);
1402 	}
1403     }
1404 
1405   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
1406   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
1407       || strcmp (h->root.root.string, "__DYNAMIC") == 0
1408       || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
1409     sym->st_shndx = SHN_ABS;
1410 
1411   return TRUE;
1412 }
1413 
1414 #define GET_SYMBOL_OR_SECTION(TAG, SYMBOL, SECTION) \
1415   case TAG: \
1416     if (SYMBOL != NULL) \
1417       { \
1418 	h = elf_link_hash_lookup (elf_hash_table (info), SYMBOL, FALSE, FALSE, TRUE); \
1419       } \
1420     else if (SECTION != NULL) \
1421       { \
1422 	s = bfd_get_section_by_name (output_bfd, SECTION); \
1423 	BFD_ASSERT (s != NULL); \
1424 	do_it = TRUE; \
1425       } \
1426     break;
1427 
1428 /* Function :  elf_arc_finish_dynamic_sections
1429    Brief    :  Finish up the dynamic sections handling.
1430    Args     :  output_bfd :
1431   	       info	  :
1432   	       h	  :
1433   	       sym	  :
1434    Returns  : True/False as the return status.  */
1435 static bfd_boolean
1436 elf_arc_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info)
1437 {
1438   struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
1439   bfd *dynobj = (elf_hash_table (info))->dynobj;
1440 
1441   if (ds.sdyn)
1442     {
1443       Elf32_External_Dyn *dyncon, *dynconend;
1444 
1445       dyncon = (Elf32_External_Dyn *) ds.sdyn->contents;
1446       dynconend =
1447 	  (Elf32_External_Dyn *) (ds.sdyn->contents + ds.sdyn->size);
1448       for (; dyncon < dynconend; dyncon++)
1449 	{
1450 	  Elf_Internal_Dyn internal_dyn;
1451 	  bfd_boolean	  do_it = FALSE;
1452 
1453 	  struct elf_link_hash_entry *h = NULL;
1454 	  asection	 *s = NULL;
1455 
1456 	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &internal_dyn);
1457 
1458 	  switch (internal_dyn.d_tag)
1459 	    {
1460 	      GET_SYMBOL_OR_SECTION (DT_INIT, "_init", NULL)
1461 	      GET_SYMBOL_OR_SECTION (DT_FINI, "_fini", NULL)
1462 	      GET_SYMBOL_OR_SECTION (DT_PLTGOT, NULL, ".plt")
1463 	      GET_SYMBOL_OR_SECTION (DT_JMPREL, NULL, ".rela.plt")
1464 	      GET_SYMBOL_OR_SECTION (DT_PLTRELSZ, NULL, ".rela.plt")
1465 	      GET_SYMBOL_OR_SECTION (DT_RELASZ, NULL, ".rela.plt")
1466 	      default:
1467 		break;
1468 	    }
1469 
1470 	  /* In case the dynamic symbols should be updated with a
1471 	     symbol.  */
1472 	  if (h != NULL
1473 	      && (h->root.type == bfd_link_hash_defined
1474 		  || h->root.type == bfd_link_hash_defweak)
1475 	      )
1476 	    {
1477 	      asection	     *asec_ptr;
1478 
1479 	      internal_dyn.d_un.d_val = h->root.u.def.value;
1480 	      asec_ptr = h->root.u.def.section;
1481 	      if (asec_ptr->output_section != NULL)
1482 		{
1483 		  internal_dyn.d_un.d_val +=
1484 		    (asec_ptr->output_section->vma +
1485 		     asec_ptr->output_offset);
1486 		}
1487 	      else
1488 		{
1489 		  /* The symbol is imported from another
1490 		     shared library and does not apply to this
1491 		     one.  */
1492 		  internal_dyn.d_un.d_val = 0;
1493 		}
1494 	      do_it = TRUE;
1495 	    }
1496 	  else if (s != NULL) /* With a section information.  */
1497 	    {
1498 	      switch (internal_dyn.d_tag)
1499 		{
1500 		  case DT_PLTGOT:
1501 		  case DT_JMPREL:
1502 		    internal_dyn.d_un.d_ptr = s->vma;
1503 		    do_it = TRUE;
1504 		    break;
1505 
1506 		  case DT_PLTRELSZ:
1507 		    internal_dyn.d_un.d_val = s->size;
1508 		    do_it = TRUE;
1509 		    break;
1510 
1511 		  case DT_RELASZ:
1512 		    internal_dyn.d_un.d_val -= s->size;
1513 		    do_it = TRUE;
1514 		    break;
1515 
1516 		  default:
1517 		    break;
1518 		}
1519 	    }
1520 
1521 	  if (do_it == TRUE)
1522 	    bfd_elf32_swap_dyn_out (output_bfd, &internal_dyn, dyncon);
1523 	}
1524 
1525       if (ds.splt->size > 0)
1526 	{
1527 	  relocate_plt_for_entry (info);
1528 	}
1529 
1530       elf_section_data (ds.srelplt->output_section)->this_hdr.sh_entsize = 0xc;
1531     }
1532 
1533   /* Fill in the first three entries in the global offset table.  */
1534   if (ds.sgot)
1535     {
1536       if (ds.sgot->size > 0)
1537 	{
1538 	  if (ds.sdyn == NULL)
1539 	    bfd_put_32 (output_bfd, (bfd_vma) 0,
1540 			ds.sgotplt->contents);
1541 	  else
1542 	    bfd_put_32 (output_bfd,
1543 			ds.sdyn->output_section->vma + ds.sdyn->output_offset,
1544 			ds.sgotplt->contents);
1545 	  bfd_put_32 (output_bfd, (bfd_vma) 0, ds.sgotplt->contents + 4);
1546 	  bfd_put_32 (output_bfd, (bfd_vma) 0, ds.sgotplt->contents + 8);
1547 
1548 	  elf_section_data (ds.sgot->output_section)->this_hdr.sh_entsize = 4;
1549 	}
1550     }
1551 
1552   if (ds.srelgot
1553       /* Check that the linker script has not dumped the .srelgot section.  */
1554       && ds.srelgot->output_section
1555       && elf_section_data (ds.srelgot->output_section))
1556     {
1557       /* TODO: Make it work even if I remove this.  */
1558       elf_section_data (ds.srelgot->output_section)->this_hdr.sh_entsize = 0xc;
1559     }
1560 
1561   return TRUE;
1562 }
1563 
1564 #define ADD_DYNAMIC_SYMBOL(NAME, TAG) \
1565   h =  elf_link_hash_lookup (elf_hash_table (info), NAME, FALSE, FALSE, FALSE); \
1566   if ((h != NULL && (h->ref_regular || h->def_regular))) \
1567     if (! _bfd_elf_add_dynamic_entry (info, TAG, 0)) \
1568       return FALSE;
1569 
1570 /* Set the sizes of the dynamic sections.  */
1571 static bfd_boolean
1572 elf_arc_size_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info)
1573 {
1574   bfd *           dynobj;
1575   asection *      s;
1576   bfd_boolean	  relocs_exist;
1577   bfd_boolean	  reltext_exist;
1578   struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
1579 
1580   dynobj = (elf_hash_table (info))->dynobj;
1581   BFD_ASSERT (dynobj != NULL);
1582 
1583   if ((elf_hash_table (info))->dynamic_sections_created)
1584     {
1585       struct elf_link_hash_entry *h;
1586 
1587       /* Set the contents of the .interp section to the interpreter.  */
1588       if (!bfd_link_pic (info))
1589 	{
1590 	  s = bfd_get_section_by_name (dynobj, ".interp");
1591 	  BFD_ASSERT (s != NULL);
1592 	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
1593 	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
1594 	}
1595 
1596       /* Add some entries to the .dynamic section.  We fill in some of the
1597          values later, in elf_bfd_final_link, but we must add the entries
1598          now so that we know the final size of the .dynamic section.
1599          Checking if the .init section is present.  We also create DT_INIT
1600          and DT_FINI entries if the init_str has been changed by the user.  */
1601 
1602       ADD_DYNAMIC_SYMBOL ("init", DT_INIT);
1603       ADD_DYNAMIC_SYMBOL ("fini", DT_FINI);
1604     }
1605   else
1606     {
1607       /* We may have created entries in the .rela.got section.  However, if
1608          we are not creating the dynamic sections, we will not actually
1609          use these entries.  Reset the size of .rela.got, which will cause
1610          it to get stripped from the output file below.  */
1611       ds.srelgot->size = 0;
1612     }
1613 
1614   for (s = dynobj->sections; s != NULL; s = s->next)
1615     {
1616 	bfd_boolean	is_dynamic_section = FALSE;
1617 
1618 	/* Skip any non dynamic section.  */
1619 	if (strstr (s->name, ".plt") != NULL
1620 	    || strstr (s->name, ".got") != NULL
1621 	  || strstr (s->name, ".rel") != NULL)
1622 	is_dynamic_section = TRUE;
1623 
1624       /* Allocate memory for the section contents.  */
1625       if (!is_dynamic_section)
1626 	continue;
1627 
1628       s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
1629       if (s->contents == NULL && s->size != 0)
1630 	  return FALSE;
1631 
1632       if (s->size == 0)
1633 	{
1634 	  s->flags |= SEC_EXCLUDE;
1635 	  continue;
1636 	}
1637 
1638       if (strcmp (s->name, ".rela.plt") != 0)
1639 	{
1640 	  const char *outname = bfd_get_section_name (output_bfd,
1641 						      s->output_section);
1642 	  asection *target = bfd_get_section_by_name (output_bfd,
1643 						      outname + 4);
1644 
1645 	  relocs_exist = TRUE;
1646 	  if (target != NULL && target->size != 0
1647 	      && (target->flags & SEC_READONLY) != 0
1648 	      && (target->flags & SEC_ALLOC) != 0)
1649 	    reltext_exist = TRUE;
1650 	}
1651     }
1652 
1653   if (ds.sdyn)
1654     {
1655       if (ds.splt && ds.splt->size != 0)
1656 	if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
1657 	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
1658 	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
1659 	    || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0)
1660 	   )
1661 	  return FALSE;
1662 
1663       if (relocs_exist == TRUE)
1664 	if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
1665 	    || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
1666 	    || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
1667 					    sizeof (Elf32_External_Rela))
1668 	   )
1669 	  return FALSE;
1670 
1671       if (reltext_exist == TRUE)
1672 	if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
1673 	  return FALSE;
1674     }
1675 
1676   return TRUE;
1677 }
1678 
1679 
1680 #define TARGET_LITTLE_SYM   arc_elf32_le_vec
1681 #define TARGET_LITTLE_NAME  "elf32-littlearc"
1682 #define TARGET_BIG_SYM	    arc_elf32_be_vec
1683 #define TARGET_BIG_NAME     "elf32-bigarc"
1684 #define ELF_ARCH	    bfd_arch_arc
1685 #define ELF_MACHINE_CODE    EM_ARC_COMPACT
1686 #define ELF_MACHINE_ALT1    EM_ARC_COMPACT2
1687 #define ELF_MAXPAGESIZE     0x2000
1688 
1689 #define elf_info_to_howto_rel		     arc_info_to_howto_rel
1690 #define elf_backend_object_p		     arc_elf_object_p
1691 #define elf_backend_final_write_processing   arc_elf_final_write_processing
1692 
1693 #define elf_backend_relocate_section	     elf_arc_relocate_section
1694 #define elf_backend_check_relocs	     elf_arc_check_relocs
1695 #define elf_backend_create_dynamic_sections  _bfd_elf_create_dynamic_sections
1696 
1697 #define elf_backend_adjust_dynamic_symbol    elf_arc_adjust_dynamic_symbol
1698 #define elf_backend_finish_dynamic_symbol    elf_arc_finish_dynamic_symbol
1699 
1700 #define elf_backend_finish_dynamic_sections  elf_arc_finish_dynamic_sections
1701 #define elf_backend_size_dynamic_sections    elf_arc_size_dynamic_sections
1702 
1703 #define elf_backend_can_gc_sections	1
1704 #define elf_backend_want_got_plt	1
1705 #define elf_backend_plt_readonly	1
1706 #define elf_backend_want_plt_sym	0
1707 #define elf_backend_got_header_size	12
1708 
1709 #define elf_backend_may_use_rel_p	0
1710 #define elf_backend_may_use_rela_p	1
1711 #define elf_backend_default_use_rela_p	1
1712 
1713 #include "elf32-target.h"
1714