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