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