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