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