]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/arc-got.h
Updated French translation for the ld subdirectory.
[thirdparty/binutils-gdb.git] / bfd / arc-got.h
CommitLineData
08759e0f 1/* ARC-specific support for 32-bit ELF
219d1afa 2 Copyright (C) 1994-2018 Free Software Foundation, Inc.
08759e0f
CM
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#ifndef ARC_GOT_H
23#define ARC_GOT_H
24
a0abe743
CM
25#define TCB_SIZE (8)
26
0411fca5
CM
27#define align_power(addr, align) \
28 (((addr) + ((bfd_vma) 1 << (align)) - 1) & (-((bfd_vma) 1 << (align))))
29
08759e0f
CM
30enum tls_type_e
31{
32 GOT_UNKNOWN = 0,
33 GOT_NORMAL,
34 GOT_TLS_GD,
35 GOT_TLS_IE,
36 GOT_TLS_LE
37};
38
39enum tls_got_entries
40{
41 TLS_GOT_NONE = 0,
42 TLS_GOT_MOD,
43 TLS_GOT_OFF,
44 TLS_GOT_MOD_AND_OFF
45};
46
47struct got_entry
48{
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;
55};
56
0f206410
CZ
57/* Return the local got list, if not defined, create an empty one. */
58
08759e0f
CM
59static struct got_entry **
60arc_get_local_got_ents (bfd * abfd)
61{
0f206410 62 if (elf_local_got_ents (abfd) == NULL)
08759e0f 63 {
0f206410
CZ
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)
68 {
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;
73 }
08759e0f
CM
74 }
75
0f206410 76 return elf_local_got_ents (abfd);
08759e0f
CM
77}
78
79static struct got_entry *
80got_entry_for_type (struct got_entry **list,
81 enum tls_type_e type)
82{
83 struct got_entry **p = list;
f7e8b360 84
08759e0f
CM
85 while (*p != NULL)
86 {
87 if ((*p)->type == type)
88 return *p;
89 p = &((*p)->next);
90 }
91 return NULL;
92}
93
94static void
95new_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)
99{
100 /* Find list end. Avoid having multiple entries of the same
101 type. */
102 struct got_entry **p = list;
f7e8b360
NC
103 struct got_entry *entry;
104
08759e0f
CM
105 while (*p != NULL)
106 {
107 if ((*p)->type == type)
108 return;
109 p = &((*p)->next);
110 }
111
f7e8b360 112 entry = (struct got_entry *) xmalloc (sizeof (struct got_entry));
08759e0f
CM
113
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;
120
121 ARC_DEBUG ("New GOT got entry added to list: "
f7e8b360
NC
122 "type: %d, offset: %ld, existing_entries: %d\n",
123 type, (long) offset, existing_entries);
08759e0f
CM
124
125 /* Add the entry to the end of the list. */
126 *p = entry;
127}
128
129static enum tls_type_e
130tls_type_for_reloc (reloc_howto_type *howto)
131{
132 enum tls_type_e ret = GOT_UNKNOWN;
f7e8b360 133
08759e0f 134 if (is_reloc_for_GOT (howto))
f7e8b360
NC
135 return GOT_NORMAL;
136
137 switch (howto->type)
08759e0f 138 {
f7e8b360
NC
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;
08759e0f 151 }
f7e8b360 152
08759e0f
CM
153 return ret;
154};
155
156static struct got_entry **
157get_got_entry_list_for_symbol (bfd *abfd,
158 unsigned long r_symndx,
159 struct elf_link_hash_entry *h)
160{
854b8506
CM
161 struct elf_arc_link_hash_entry *h1 =
162 ((struct elf_arc_link_hash_entry *) h);
163 if (h1 != NULL)
08759e0f 164 {
854b8506 165 return &h1->got_ents;
08759e0f
CM
166 }
167 else
168 {
0f206410 169 return arc_get_local_got_ents (abfd) + r_symndx;
08759e0f
CM
170 }
171}
172
173
174static enum tls_type_e
175arc_got_entry_type_for_reloc (reloc_howto_type *howto)
176{
177 enum tls_type_e type = GOT_UNKNOWN;
178
179 if (is_reloc_for_GOT (howto))
f7e8b360
NC
180 return GOT_NORMAL;
181
182 if (is_reloc_for_TLS (howto))
08759e0f
CM
183 {
184 switch (howto->type)
185 {
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;
194 }
195 }
196 return type;
197}
198
199#define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
200 htab->s##SECNAME->size; \
201 { \
202 if (COND_FOR_RELOC) \
203 { \
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)); \
209 } \
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; \
215 } \
216
217static bfd_boolean
218arc_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)
222{
223 struct elf_link_hash_table *htab = elf_hash_table (info);
224
225 if (got_entry_for_type (list, type) != NULL)
226 return TRUE;
227
228 switch (type)
229 {
230 case GOT_NORMAL:
231 {
07d6d2b8 232 bfd_vma offset
08759e0f
CM
233 = ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info)
234 || h != NULL, h);
07d6d2b8 235 new_got_entry_to_list (list, type, offset, TLS_GOT_NONE);
08759e0f
CM
236 }
237 break;
238
239
240 case GOT_TLS_GD:
241 {
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);
247 }
248 break;
249 case GOT_TLS_IE:
250 case GOT_TLS_LE:
251 {
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);
255 }
256 break;
257
258 default:
259 return FALSE;
260 break;
261 }
262 return TRUE;
263}
264
265
266static bfd_vma
07d6d2b8
AM
267relocate_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,
f7e8b360 275 struct arc_relocation_data * reloc_data)
08759e0f 276{
f7e8b360
NC
277 struct elf_link_hash_table *htab = elf_hash_table (info);
278 struct got_entry *entry = NULL;
08759e0f
CM
279
280 if (list_p == NULL || type == GOT_UNKNOWN || type == GOT_TLS_LE)
281 return 0;
282
08759e0f
CM
283 entry = got_entry_for_type (list_p, type);
284 BFD_ASSERT (entry);
285
286 if (h == NULL
287 || (! elf_hash_table (info)->dynamic_sections_created
288 || (bfd_link_pic (info)
f7e8b360 289 && SYMBOL_REFERENCES_LOCAL (info, h))))
08759e0f
CM
290 {
291 const char ATTRIBUTE_UNUSED *symbol_name;
292 static const char local_name[] = "(local)";
293 asection *tls_sec = NULL;
294 bfd_vma sym_value = 0;
295
296 if (h != NULL)
297 {
298 // TODO: This should not be here.
299 reloc_data->sym_value = h->root.u.def.value;
300 reloc_data->sym_section = h->root.u.def.section;
301
302 sym_value = h->root.u.def.value
f7e8b360
NC
303 + h->root.u.def.section->output_section->vma
304 + h->root.u.def.section->output_offset;
08759e0f
CM
305
306 tls_sec = elf_hash_table (info)->tls_sec;
307
308 symbol_name = h->root.root.string;
309 }
310 else
311 {
312 Elf_Internal_Sym *sym = local_syms + r_symndx;
313 asection *sec = local_sections[r_symndx];
314
315 sym_value = sym->st_value
f7e8b360
NC
316 + sec->output_section->vma
317 + sec->output_offset;
08759e0f
CM
318
319 tls_sec = elf_hash_table (info)->tls_sec;
320
321 symbol_name = local_name;
322 }
323
324
535b785f 325 if (entry && !entry->processed)
08759e0f
CM
326 {
327 switch (entry->type)
328 {
f7e8b360
NC
329 case GOT_TLS_GD:
330 {
331 BFD_ASSERT (tls_sec && tls_sec->output_section);
332 bfd_vma sec_vma = tls_sec->output_section->vma;
333
334 bfd_put_32 (output_bfd,
714e9a95
CM
335 sym_value - sec_vma
336 + (elf_hash_table (info)->dynamic_sections_created
337 ? 0
338 : (align_power (TCB_SIZE,
339 tls_sec->alignment_power))),
f7e8b360
NC
340 htab->sgot->contents + entry->offset
341 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
342 ? 4 : 0));
343
344 ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
4dd72ffd 345 "@ %lx, for symbol %s\n",
f7e8b360
NC
346 (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
347 "GOT_TLS_IE"),
348 (long) (sym_value - sec_vma),
4dd72ffd 349 (long) (htab->sgot->output_section->vma
714e9a95 350 + htab->sgot->output_offset
4dd72ffd
CM
351 + entry->offset
352 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
353 ? 4 : 0)),
f7e8b360
NC
354 symbol_name);
355 }
356 break;
357
358 case GOT_TLS_IE:
359 {
360 BFD_ASSERT (tls_sec && tls_sec->output_section);
361 bfd_vma ATTRIBUTE_UNUSED sec_vma
362 = tls_sec->output_section->vma;
363
4dd72ffd 364 bfd_put_32 (output_bfd,
a0abe743 365 sym_value - sec_vma
0411fca5
CM
366 + (elf_hash_table (info)->dynamic_sections_created
367 ? 0
368 : (align_power (TCB_SIZE,
369 tls_sec->alignment_power))),
4dd72ffd
CM
370 htab->sgot->contents + entry->offset
371 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
372 ? 4 : 0));
373
f7e8b360
NC
374 ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
375 "@ %p, for symbol %s\n",
376 (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
377 "GOT_TLS_IE"),
378 (long) (sym_value - sec_vma),
4dd72ffd 379 (long) (htab->sgot->output_section->vma
714e9a95 380 + htab->sgot->output_offset
4dd72ffd
CM
381 + entry->offset
382 + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
383 ? 4 : 0)),
f7e8b360
NC
384 symbol_name);
385 }
386 break;
387
388 case GOT_NORMAL:
389 {
390 bfd_vma sec_vma
391 = reloc_data->sym_section->output_section->vma
392 + reloc_data->sym_section->output_offset;
393
c02d11a5
CM
394 if (h != NULL
395 && h->root.type == bfd_link_hash_undefweak)
396 ARC_DEBUG ("arc_info: PATCHED: NOT_PATCHED "
397 "@ %#08lx for sym %s in got offset %#lx "
398 "(is undefweak)\n",
399 (long) (htab->sgot->output_section->vma
400 + htab->sgot->output_offset
401 + entry->offset),
402 symbol_name,
403 (long) entry->offset);
404 else
f7e8b360
NC
405 {
406 bfd_put_32 (output_bfd,
407 reloc_data->sym_value + sec_vma,
408 htab->sgot->contents + entry->offset);
f7e8b360
NC
409 ARC_DEBUG ("arc_info: PATCHED: %#08lx "
410 "@ %#08lx for sym %s in got offset %#lx\n",
411 (long) (reloc_data->sym_value + sec_vma),
412 (long) (htab->sgot->output_section->vma
413 + htab->sgot->output_offset + entry->offset),
414 symbol_name,
415 (long) entry->offset);
416 }
f7e8b360
NC
417 }
418 break;
419 default:
420 BFD_ASSERT (0);
421 break;
08759e0f
CM
422 }
423 entry->processed = TRUE;
424 }
425 }
426
427 return entry->offset;
428}
429
430static void
431create_got_dynrelocs_for_single_entry (struct got_entry *list,
432 bfd *output_bfd,
433 struct bfd_link_info * info,
434 struct elf_link_hash_entry *h)
435{
436 if (list == NULL)
437 return;
438
439 bfd_vma got_offset = list->offset;
440
441 if (list->type == GOT_NORMAL
535b785f 442 && !list->created_dyn_relocation)
08759e0f
CM
443 {
444 if (bfd_link_pic (info)
445 && h != NULL
446 && (info->symbolic || h->dynindx == -1)
447 && h->def_regular)
448 {
449 ADD_RELA (output_bfd, got, got_offset, 0, R_ARC_RELATIVE, 0);
450 }
451 /* Do not fully understand the side effects of this condition.
452 The relocation space might still being reserved. Perhaps
453 I should clear its value. */
454 else if (h != NULL && h->dynindx != -1)
455 {
456 ADD_RELA (output_bfd, got, got_offset, h->dynindx, R_ARC_GLOB_DAT, 0);
457 }
458 list->created_dyn_relocation = TRUE;
459 }
460 else if (list->existing_entries != TLS_GOT_NONE
535b785f 461 && !list->created_dyn_relocation)
08759e0f
CM
462 {
463 /* TODO TLS: This is not called for local symbols.
464 In order to correctly implement TLS, this should also
465 be called for all local symbols with tls got entries.
466 Should be moved to relocate_section in order to make it
467 work for local symbols. */
468 struct elf_link_hash_table *htab = elf_hash_table (info);
469 enum tls_got_entries e = list->existing_entries;
470
471 BFD_ASSERT (list->type != GOT_TLS_GD
07d6d2b8 472 || list->existing_entries == TLS_GOT_MOD_AND_OFF);
08759e0f
CM
473
474 bfd_vma dynindx = (h == NULL || h->dynindx == -1) ? 0 : h->dynindx;
475
476 if (e == TLS_GOT_MOD_AND_OFF || e == TLS_GOT_MOD)
477 {
478 ADD_RELA (output_bfd, got, got_offset, dynindx,
07d6d2b8 479 R_ARC_TLS_DTPMOD, 0);
08759e0f 480 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
f7e8b360 481GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = 0x0\n",
08759e0f 482 list->type,
f7e8b360
NC
483 (long) got_offset,
484 (long) (htab->sgot->output_section->vma
485 + htab->sgot->output_offset + got_offset),
486 (long) dynindx);
08759e0f 487 }
f7e8b360 488
08759e0f
CM
489 if (e == TLS_GOT_MOD_AND_OFF || e == TLS_GOT_OFF)
490 {
491 bfd_vma addend = 0;
492 if (list->type == GOT_TLS_IE)
a0abe743 493 {
08759e0f
CM
494 addend = bfd_get_32 (output_bfd,
495 htab->sgot->contents + got_offset);
a0abe743 496 }
08759e0f
CM
497
498 ADD_RELA (output_bfd, got,
499 got_offset + (e == TLS_GOT_MOD_AND_OFF ? 4 : 0),
500 dynindx,
501 (list->type == GOT_TLS_IE ? R_ARC_TLS_TPOFF
502 : R_ARC_TLS_DTPOFF),
503 addend);
504
505 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
f7e8b360 506GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = %#lx\n",
08759e0f 507 list->type,
f7e8b360
NC
508 (long) got_offset,
509 (long) (htab->sgot->output_section->vma
510 + htab->sgot->output_offset + got_offset),
511 (long) dynindx, (long) addend);
08759e0f
CM
512 }
513 list->created_dyn_relocation = TRUE;
514 }
515}
516
517static void
518create_got_dynrelocs_for_got_info (struct got_entry **list_p,
519 bfd *output_bfd,
520 struct bfd_link_info * info,
07d6d2b8 521 struct elf_link_hash_entry *h)
08759e0f
CM
522{
523 if (list_p == NULL)
524 return;
525
526 struct got_entry *list = *list_p;
527 /* Traverse the list of got entries for this symbol. */
528 while (list)
529 {
530 create_got_dynrelocs_for_single_entry (list, output_bfd, info, h);
531 list = list->next;
532 }
533}
534
535#undef ADD_SYMBOL_REF_SEC_AND_RELOC
536
537#endif /* ARC_GOT_H */