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