[PATCH 40/57][Arm][OBJDUMP] Add support for MVE instructions: vdup, veor, vfma, vfms...
[binutils-gdb.git] / bfd / arc-got.h
blob55c1ad72de032053da5a48561d1e0cb66345de62
1 /* ARC-specific support for 32-bit ELF
2 Copyright (C) 1994-2019 Free Software Foundation, Inc.
3 Contributed by Cupertino Miranda (cmiranda@synopsys.com).
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
22 #ifndef ARC_GOT_H
23 #define ARC_GOT_H
25 #define TCB_SIZE (8)
27 #define align_power(addr, align) \
28 (((addr) + ((bfd_vma) 1 << (align)) - 1) & (-((bfd_vma) 1 << (align))))
30 enum tls_type_e
32 GOT_UNKNOWN = 0,
33 GOT_NORMAL,
34 GOT_TLS_GD,
35 GOT_TLS_IE,
36 GOT_TLS_LE
39 enum tls_got_entries
41 TLS_GOT_NONE = 0,
42 TLS_GOT_MOD,
43 TLS_GOT_OFF,
44 TLS_GOT_MOD_AND_OFF
47 struct got_entry
49 struct got_entry *next;
50 enum tls_type_e type;
51 bfd_vma offset;
52 bfd_boolean processed;
53 bfd_boolean created_dyn_relocation;
54 enum tls_got_entries existing_entries;
57 /* Return the local got list, if not defined, create an empty one. */
59 static struct got_entry **
60 arc_get_local_got_ents (bfd * abfd)
62 if (elf_local_got_ents (abfd) == NULL)
64 bfd_size_type amt = (elf_tdata (abfd)->symtab_hdr.sh_info
65 * sizeof (*elf_local_got_ents (abfd)));
66 elf_local_got_ents (abfd) = bfd_zmalloc (amt);
67 if (elf_local_got_ents (abfd) == NULL)
69 _bfd_error_handler (_("%pB: cannot allocate memory for local "
70 "GOT entries"), abfd);
71 bfd_set_error (bfd_error_bad_value);
72 return NULL;
76 return elf_local_got_ents (abfd);
79 static struct got_entry *
80 got_entry_for_type (struct got_entry **list,
81 enum tls_type_e type)
83 struct got_entry **p = list;
85 while (*p != NULL)
87 if ((*p)->type == type)
88 return *p;
89 p = &((*p)->next);
91 return NULL;
94 static void
95 new_got_entry_to_list (struct got_entry **list,
96 enum tls_type_e type,
97 bfd_vma offset,
98 enum tls_got_entries existing_entries)
100 /* Find list end. Avoid having multiple entries of the same
101 type. */
102 struct got_entry **p = list;
103 struct got_entry *entry;
105 while (*p != NULL)
107 if ((*p)->type == type)
108 return;
109 p = &((*p)->next);
112 entry = (struct got_entry *) xmalloc (sizeof (struct got_entry));
114 entry->type = type;
115 entry->offset = offset;
116 entry->next = NULL;
117 entry->processed = FALSE;
118 entry->created_dyn_relocation = FALSE;
119 entry->existing_entries = existing_entries;
121 ARC_DEBUG ("New GOT got entry added to list: "
122 "type: %d, offset: %ld, existing_entries: %d\n",
123 type, (long) offset, existing_entries);
125 /* Add the entry to the end of the list. */
126 *p = entry;
129 static enum tls_type_e
130 tls_type_for_reloc (reloc_howto_type *howto)
132 enum tls_type_e ret = GOT_UNKNOWN;
134 if (is_reloc_for_GOT (howto))
135 return GOT_NORMAL;
137 switch (howto->type)
139 case R_ARC_TLS_GD_GOT:
140 ret = GOT_TLS_GD;
141 break;
142 case R_ARC_TLS_IE_GOT:
143 ret = GOT_TLS_IE;
144 break;
145 case R_ARC_TLS_LE_32:
146 ret = GOT_TLS_LE;
147 break;
148 default:
149 ret = GOT_UNKNOWN;
150 break;
153 return ret;
156 static struct got_entry **
157 get_got_entry_list_for_symbol (bfd *abfd,
158 unsigned long r_symndx,
159 struct elf_link_hash_entry *h)
161 struct elf_arc_link_hash_entry *h1 =
162 ((struct elf_arc_link_hash_entry *) h);
163 if (h1 != NULL)
165 return &h1->got_ents;
167 else
169 return arc_get_local_got_ents (abfd) + r_symndx;
174 static enum tls_type_e
175 arc_got_entry_type_for_reloc (reloc_howto_type *howto)
177 enum tls_type_e type = GOT_UNKNOWN;
179 if (is_reloc_for_GOT (howto))
180 return GOT_NORMAL;
182 if (is_reloc_for_TLS (howto))
184 switch (howto->type)
186 case R_ARC_TLS_GD_GOT:
187 type = GOT_TLS_GD;
188 break;
189 case R_ARC_TLS_IE_GOT:
190 type = GOT_TLS_IE;
191 break;
192 default:
193 break;
196 return type;
199 #define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
200 htab->s##SECNAME->size; \
202 if (COND_FOR_RELOC) \
204 htab->srel##SECNAME->size += sizeof (Elf32_External_Rela); \
205 ARC_DEBUG ("arc_info: Added reloc space in " \
206 #SECNAME " section at " __FILE__ \
207 ":%d for symbol %s\n", \
208 __LINE__, name_for_global_symbol (H)); \
210 if (H) \
211 if (H->dynindx == -1 && !H->forced_local) \
212 if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
213 return FALSE; \
214 htab->s##SECNAME->size += 4; \
217 static bfd_boolean
218 arc_fill_got_info_for_reloc (enum tls_type_e type,
219 struct got_entry **list,
220 struct bfd_link_info * info,
221 struct elf_link_hash_entry *h)
223 struct elf_link_hash_table *htab = elf_hash_table (info);
225 if (got_entry_for_type (list, type) != NULL)
226 return TRUE;
228 switch (type)
230 case GOT_NORMAL:
232 bfd_vma offset
233 = ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info)
234 || h != NULL, h);
235 new_got_entry_to_list (list, type, offset, TLS_GOT_NONE);
237 break;
240 case GOT_TLS_GD:
242 bfd_vma offset
243 = ADD_SYMBOL_REF_SEC_AND_RELOC (got, TRUE, h);
244 bfd_vma ATTRIBUTE_UNUSED notneeded
245 = ADD_SYMBOL_REF_SEC_AND_RELOC (got, TRUE, h);
246 new_got_entry_to_list (list, type, offset, TLS_GOT_MOD_AND_OFF);
248 break;
249 case GOT_TLS_IE:
250 case GOT_TLS_LE:
252 bfd_vma offset
253 = ADD_SYMBOL_REF_SEC_AND_RELOC (got, TRUE, h);
254 new_got_entry_to_list (list, type, offset, TLS_GOT_OFF);
256 break;
258 default:
259 return FALSE;
260 break;
262 return TRUE;
266 static bfd_vma
267 relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p,
268 enum tls_type_e type,
269 struct bfd_link_info * info,
270 bfd * output_bfd,
271 unsigned long r_symndx,
272 Elf_Internal_Sym * local_syms,
273 asection ** local_sections,
274 struct elf_link_hash_entry * h,
275 struct arc_relocation_data * reloc_data)
277 struct elf_link_hash_table *htab = elf_hash_table (info);
278 struct got_entry *entry = NULL;
280 if (list_p == NULL || type == GOT_UNKNOWN || type == GOT_TLS_LE)
281 return 0;
283 entry = got_entry_for_type (list_p, type);
284 BFD_ASSERT (entry);
286 if (h == NULL
287 || h->forced_local == TRUE
288 || (! elf_hash_table (info)->dynamic_sections_created
289 || (bfd_link_pic (info)
290 && SYMBOL_REFERENCES_LOCAL (info, h))))
292 const char ATTRIBUTE_UNUSED *symbol_name;
293 static const char local_name[] = "(local)";
294 asection *tls_sec = NULL;
295 bfd_vma sym_value = 0;
297 if (h != NULL)
299 // TODO: This should not be here.
300 reloc_data->sym_value = h->root.u.def.value;
301 reloc_data->sym_section = h->root.u.def.section;
303 sym_value = h->root.u.def.value
304 + h->root.u.def.section->output_section->vma
305 + h->root.u.def.section->output_offset;
307 tls_sec = elf_hash_table (info)->tls_sec;
309 symbol_name = h->root.root.string;
311 else
313 Elf_Internal_Sym *sym = local_syms + r_symndx;
314 asection *sec = local_sections[r_symndx];
316 sym_value = sym->st_value
317 + sec->output_section->vma
318 + sec->output_offset;
320 tls_sec = elf_hash_table (info)->tls_sec;
322 symbol_name = local_name;
326 if (entry && !entry->processed)
328 switch (entry->type)
330 case GOT_TLS_GD:
332 BFD_ASSERT (tls_sec && tls_sec->output_section);
333 bfd_vma sec_vma = tls_sec->output_section->vma;
335 if (h == NULL || h->forced_local
336 || !elf_hash_table (info)->dynamic_sections_created)
338 bfd_put_32 (output_bfd,
339 sym_value - sec_vma
340 + (elf_hash_table (info)->dynamic_sections_created
342 : (align_power (0,
343 tls_sec->alignment_power))),
344 htab->sgot->contents + entry->offset
345 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
346 ? 4 : 0));
348 ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
349 "@ %lx, for symbol %s\n",
350 (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
351 "GOT_TLS_IE"),
352 (long) (sym_value - sec_vma),
353 (long) (htab->sgot->output_section->vma
354 + htab->sgot->output_offset
355 + entry->offset
356 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
357 ? 4 : 0)),
358 symbol_name);
361 break;
363 case GOT_TLS_IE:
365 BFD_ASSERT (tls_sec && tls_sec->output_section);
366 bfd_vma ATTRIBUTE_UNUSED sec_vma
367 = tls_sec->output_section->vma;
369 bfd_put_32 (output_bfd,
370 sym_value - sec_vma
371 + (elf_hash_table (info)->dynamic_sections_created
373 : (align_power (TCB_SIZE,
374 tls_sec->alignment_power))),
375 htab->sgot->contents + entry->offset
376 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
377 ? 4 : 0));
379 ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
380 "@ %p, for symbol %s\n",
381 (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
382 "GOT_TLS_IE"),
383 (long) (sym_value - sec_vma),
384 (long) (htab->sgot->output_section->vma
385 + htab->sgot->output_offset
386 + entry->offset
387 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
388 ? 4 : 0)),
389 symbol_name);
391 break;
393 case GOT_NORMAL:
395 bfd_vma sec_vma
396 = reloc_data->sym_section->output_section->vma
397 + reloc_data->sym_section->output_offset;
399 if (h != NULL
400 && h->root.type == bfd_link_hash_undefweak)
401 ARC_DEBUG ("arc_info: PATCHED: NOT_PATCHED "
402 "@ %#08lx for sym %s in got offset %#lx "
403 "(is undefweak)\n",
404 (long) (htab->sgot->output_section->vma
405 + htab->sgot->output_offset
406 + entry->offset),
407 symbol_name,
408 (long) entry->offset);
409 else
411 bfd_put_32 (output_bfd,
412 reloc_data->sym_value + sec_vma,
413 htab->sgot->contents + entry->offset);
414 ARC_DEBUG ("arc_info: PATCHED: %#08lx "
415 "@ %#08lx for sym %s in got offset %#lx\n",
416 (long) (reloc_data->sym_value + sec_vma),
417 (long) (htab->sgot->output_section->vma
418 + htab->sgot->output_offset + entry->offset),
419 symbol_name,
420 (long) entry->offset);
423 break;
424 default:
425 BFD_ASSERT (0);
426 break;
428 entry->processed = TRUE;
432 return entry->offset;
435 static void
436 create_got_dynrelocs_for_single_entry (struct got_entry *list,
437 bfd *output_bfd,
438 struct bfd_link_info * info,
439 struct elf_link_hash_entry *h)
441 if (list == NULL)
442 return;
444 bfd_vma got_offset = list->offset;
446 if (list->type == GOT_NORMAL
447 && !list->created_dyn_relocation)
449 if (bfd_link_pic (info)
450 && h != NULL
451 && (info->symbolic || h->dynindx == -1)
452 && h->def_regular)
454 ADD_RELA (output_bfd, got, got_offset, 0, R_ARC_RELATIVE, 0);
456 /* Do not fully understand the side effects of this condition.
457 The relocation space might still being reserved. Perhaps
458 I should clear its value. */
459 else if (h != NULL && h->dynindx != -1)
461 ADD_RELA (output_bfd, got, got_offset, h->dynindx, R_ARC_GLOB_DAT, 0);
463 list->created_dyn_relocation = TRUE;
465 else if (list->existing_entries != TLS_GOT_NONE
466 && !list->created_dyn_relocation)
468 /* TODO TLS: This is not called for local symbols.
469 In order to correctly implement TLS, this should also
470 be called for all local symbols with tls got entries.
471 Should be moved to relocate_section in order to make it
472 work for local symbols. */
473 struct elf_link_hash_table *htab = elf_hash_table (info);
474 enum tls_got_entries e = list->existing_entries;
476 BFD_ASSERT (list->type != GOT_TLS_GD
477 || list->existing_entries == TLS_GOT_MOD_AND_OFF);
479 bfd_vma dynindx = (h == NULL || h->dynindx == -1) ? 0 : h->dynindx;
481 if (e == TLS_GOT_MOD_AND_OFF || e == TLS_GOT_MOD)
483 ADD_RELA (output_bfd, got, got_offset, dynindx,
484 R_ARC_TLS_DTPMOD, 0);
485 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
486 GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = 0x0\n",
487 list->type,
488 (long) got_offset,
489 (long) (htab->sgot->output_section->vma
490 + htab->sgot->output_offset + got_offset),
491 (long) dynindx);
494 if (e == TLS_GOT_MOD_AND_OFF || e == TLS_GOT_OFF)
496 bfd_vma addend = 0;
497 if (list->type == GOT_TLS_IE)
499 addend = bfd_get_32 (output_bfd,
500 htab->sgot->contents + got_offset);
503 ADD_RELA (output_bfd, got,
504 got_offset + (e == TLS_GOT_MOD_AND_OFF ? 4 : 0),
505 dynindx,
506 (list->type == GOT_TLS_IE ? R_ARC_TLS_TPOFF
507 : R_ARC_TLS_DTPOFF),
508 addend);
510 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
511 GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = %#lx\n",
512 list->type,
513 (long) got_offset,
514 (long) (htab->sgot->output_section->vma
515 + htab->sgot->output_offset + got_offset),
516 (long) dynindx, (long) addend);
518 list->created_dyn_relocation = TRUE;
522 static void
523 create_got_dynrelocs_for_got_info (struct got_entry **list_p,
524 bfd *output_bfd,
525 struct bfd_link_info * info,
526 struct elf_link_hash_entry *h)
528 if (list_p == NULL)
529 return;
531 struct got_entry *list = *list_p;
532 /* Traverse the list of got entries for this symbol. */
533 while (list)
535 create_got_dynrelocs_for_single_entry (list, output_bfd, info, h);
536 list = list->next;
540 #undef ADD_SYMBOL_REF_SEC_AND_RELOC
542 #endif /* ARC_GOT_H */