1 /* ARC-specific support for 32-bit ELF
2 Copyright (C) 1994-2018 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. */
27 #define align_power(addr, align) \
28 (((addr) + ((bfd_vma) 1 << (align)) - 1) & (-((bfd_vma) 1 << (align))))
49 struct got_entry
*next
;
52 bfd_boolean processed
;
53 bfd_boolean created_dyn_relocation
;
54 enum tls_got_entries existing_entries
;
57 static struct got_entry
**
58 arc_get_local_got_ents (bfd
* abfd
)
60 static struct got_entry
**local_got_ents
= NULL
;
62 if (local_got_ents
== NULL
)
65 Elf_Internal_Shdr
*symtab_hdr
= &((elf_tdata (abfd
))->symtab_hdr
);
67 size
= symtab_hdr
->sh_info
* sizeof (bfd_vma
);
68 local_got_ents
= (struct got_entry
**)
69 bfd_alloc (abfd
, sizeof (struct got_entry
*) * size
);
70 if (local_got_ents
== NULL
)
73 memset (local_got_ents
, 0, sizeof (struct got_entry
*) * size
);
74 elf_local_got_ents (abfd
) = local_got_ents
;
77 return local_got_ents
;
80 static struct got_entry
*
81 got_entry_for_type (struct got_entry
**list
,
84 struct got_entry
**p
= list
;
88 if ((*p
)->type
== type
)
96 new_got_entry_to_list (struct got_entry
**list
,
99 enum tls_got_entries existing_entries
)
101 /* Find list end. Avoid having multiple entries of the same
103 struct got_entry
**p
= list
;
104 struct got_entry
*entry
;
108 if ((*p
)->type
== type
)
113 entry
= (struct got_entry
*) xmalloc (sizeof (struct got_entry
));
116 entry
->offset
= offset
;
118 entry
->processed
= FALSE
;
119 entry
->created_dyn_relocation
= FALSE
;
120 entry
->existing_entries
= existing_entries
;
122 ARC_DEBUG ("New GOT got entry added to list: "
123 "type: %d, offset: %ld, existing_entries: %d\n",
124 type
, (long) offset
, existing_entries
);
126 /* Add the entry to the end of the list. */
130 static enum tls_type_e
131 tls_type_for_reloc (reloc_howto_type
*howto
)
133 enum tls_type_e ret
= GOT_UNKNOWN
;
135 if (is_reloc_for_GOT (howto
))
140 case R_ARC_TLS_GD_GOT
:
143 case R_ARC_TLS_IE_GOT
:
146 case R_ARC_TLS_LE_32
:
157 static struct got_entry
**
158 get_got_entry_list_for_symbol (bfd
*abfd
,
159 unsigned long r_symndx
,
160 struct elf_link_hash_entry
*h
)
162 struct elf_arc_link_hash_entry
*h1
=
163 ((struct elf_arc_link_hash_entry
*) h
);
166 return &h1
->got_ents
;
170 struct got_entry
**local_got_ents
171 = arc_get_local_got_ents (abfd
);
172 return &local_got_ents
[r_symndx
];
177 static enum tls_type_e
178 arc_got_entry_type_for_reloc (reloc_howto_type
*howto
)
180 enum tls_type_e type
= GOT_UNKNOWN
;
182 if (is_reloc_for_GOT (howto
))
185 if (is_reloc_for_TLS (howto
))
189 case R_ARC_TLS_GD_GOT
:
192 case R_ARC_TLS_IE_GOT
:
202 #define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
203 htab->s##SECNAME->size; \
205 if (COND_FOR_RELOC) \
207 htab->srel##SECNAME->size += sizeof (Elf32_External_Rela); \
208 ARC_DEBUG ("arc_info: Added reloc space in " \
209 #SECNAME " section at " __FILE__ \
210 ":%d for symbol %s\n", \
211 __LINE__, name_for_global_symbol (H)); \
214 if (h->dynindx == -1 && !h->forced_local) \
215 if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
217 htab->s##SECNAME->size += 4; \
221 arc_fill_got_info_for_reloc (enum tls_type_e type
,
222 struct got_entry
**list
,
223 struct bfd_link_info
* info
,
224 struct elf_link_hash_entry
*h
)
226 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
228 if (got_entry_for_type (list
, type
) != NULL
)
236 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, bfd_link_pic (info
)
238 new_got_entry_to_list (list
, type
, offset
, TLS_GOT_NONE
);
246 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, TRUE
, h
);
247 bfd_vma ATTRIBUTE_UNUSED notneeded
248 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, TRUE
, h
);
249 new_got_entry_to_list (list
, type
, offset
, TLS_GOT_MOD_AND_OFF
);
256 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, TRUE
, h
);
257 new_got_entry_to_list (list
, type
, offset
, TLS_GOT_OFF
);
270 relocate_fix_got_relocs_for_got_info (struct got_entry
** list_p
,
271 enum tls_type_e type
,
272 struct bfd_link_info
* info
,
274 unsigned long r_symndx
,
275 Elf_Internal_Sym
* local_syms
,
276 asection
** local_sections
,
277 struct elf_link_hash_entry
* h
,
278 struct arc_relocation_data
* reloc_data
)
280 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
281 struct got_entry
*entry
= NULL
;
283 if (list_p
== NULL
|| type
== GOT_UNKNOWN
|| type
== GOT_TLS_LE
)
286 entry
= got_entry_for_type (list_p
, type
);
290 || (! elf_hash_table (info
)->dynamic_sections_created
291 || (bfd_link_pic (info
)
292 && SYMBOL_REFERENCES_LOCAL (info
, h
))))
294 const char ATTRIBUTE_UNUSED
*symbol_name
;
295 static const char local_name
[] = "(local)";
296 asection
*tls_sec
= NULL
;
297 bfd_vma sym_value
= 0;
301 // TODO: This should not be here.
302 reloc_data
->sym_value
= h
->root
.u
.def
.value
;
303 reloc_data
->sym_section
= h
->root
.u
.def
.section
;
305 sym_value
= h
->root
.u
.def
.value
306 + h
->root
.u
.def
.section
->output_section
->vma
307 + h
->root
.u
.def
.section
->output_offset
;
309 tls_sec
= elf_hash_table (info
)->tls_sec
;
311 symbol_name
= h
->root
.root
.string
;
315 Elf_Internal_Sym
*sym
= local_syms
+ r_symndx
;
316 asection
*sec
= local_sections
[r_symndx
];
318 sym_value
= sym
->st_value
319 + sec
->output_section
->vma
320 + sec
->output_offset
;
322 tls_sec
= elf_hash_table (info
)->tls_sec
;
324 symbol_name
= local_name
;
328 if (entry
&& !entry
->processed
)
334 BFD_ASSERT (tls_sec
&& tls_sec
->output_section
);
335 bfd_vma sec_vma
= tls_sec
->output_section
->vma
;
337 bfd_put_32 (output_bfd
,
339 + (elf_hash_table (info
)->dynamic_sections_created
341 : (align_power (TCB_SIZE
,
342 tls_sec
->alignment_power
))),
343 htab
->sgot
->contents
+ entry
->offset
344 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
347 ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
348 "@ %lx, for symbol %s\n",
349 (entry
->type
== GOT_TLS_GD
? "GOT_TLS_GD" :
351 (long) (sym_value
- sec_vma
),
352 (long) (htab
->sgot
->output_section
->vma
353 + htab
->sgot
->output_offset
355 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
363 BFD_ASSERT (tls_sec
&& tls_sec
->output_section
);
364 bfd_vma ATTRIBUTE_UNUSED sec_vma
365 = tls_sec
->output_section
->vma
;
367 bfd_put_32 (output_bfd
,
369 + (elf_hash_table (info
)->dynamic_sections_created
371 : (align_power (TCB_SIZE
,
372 tls_sec
->alignment_power
))),
373 htab
->sgot
->contents
+ entry
->offset
374 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
377 ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
378 "@ %p, for symbol %s\n",
379 (entry
->type
== GOT_TLS_GD
? "GOT_TLS_GD" :
381 (long) (sym_value
- sec_vma
),
382 (long) (htab
->sgot
->output_section
->vma
383 + htab
->sgot
->output_offset
385 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
394 = reloc_data
->sym_section
->output_section
->vma
395 + reloc_data
->sym_section
->output_offset
;
398 && h
->root
.type
== bfd_link_hash_undefweak
)
399 ARC_DEBUG ("arc_info: PATCHED: NOT_PATCHED "
400 "@ %#08lx for sym %s in got offset %#lx "
402 (long) (htab
->sgot
->output_section
->vma
403 + htab
->sgot
->output_offset
406 (long) entry
->offset
);
409 bfd_put_32 (output_bfd
,
410 reloc_data
->sym_value
+ sec_vma
,
411 htab
->sgot
->contents
+ entry
->offset
);
412 ARC_DEBUG ("arc_info: PATCHED: %#08lx "
413 "@ %#08lx for sym %s in got offset %#lx\n",
414 (long) (reloc_data
->sym_value
+ sec_vma
),
415 (long) (htab
->sgot
->output_section
->vma
416 + htab
->sgot
->output_offset
+ entry
->offset
),
418 (long) entry
->offset
);
426 entry
->processed
= TRUE
;
430 return entry
->offset
;
434 create_got_dynrelocs_for_single_entry (struct got_entry
*list
,
436 struct bfd_link_info
* info
,
437 struct elf_link_hash_entry
*h
)
442 bfd_vma got_offset
= list
->offset
;
444 if (list
->type
== GOT_NORMAL
445 && !list
->created_dyn_relocation
)
447 if (bfd_link_pic (info
)
449 && (info
->symbolic
|| h
->dynindx
== -1)
452 ADD_RELA (output_bfd
, got
, got_offset
, 0, R_ARC_RELATIVE
, 0);
454 /* Do not fully understand the side effects of this condition.
455 The relocation space might still being reserved. Perhaps
456 I should clear its value. */
457 else if (h
!= NULL
&& h
->dynindx
!= -1)
459 ADD_RELA (output_bfd
, got
, got_offset
, h
->dynindx
, R_ARC_GLOB_DAT
, 0);
461 list
->created_dyn_relocation
= TRUE
;
463 else if (list
->existing_entries
!= TLS_GOT_NONE
464 && !list
->created_dyn_relocation
)
466 /* TODO TLS: This is not called for local symbols.
467 In order to correctly implement TLS, this should also
468 be called for all local symbols with tls got entries.
469 Should be moved to relocate_section in order to make it
470 work for local symbols. */
471 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
472 enum tls_got_entries e
= list
->existing_entries
;
474 BFD_ASSERT (list
->type
!= GOT_TLS_GD
475 || list
->existing_entries
== TLS_GOT_MOD_AND_OFF
);
477 bfd_vma dynindx
= (h
== NULL
|| h
->dynindx
== -1) ? 0 : h
->dynindx
;
479 if (e
== TLS_GOT_MOD_AND_OFF
|| e
== TLS_GOT_MOD
)
481 ADD_RELA (output_bfd
, got
, got_offset
, dynindx
,
482 R_ARC_TLS_DTPMOD
, 0);
483 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
484 GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = 0x0\n",
487 (long) (htab
->sgot
->output_section
->vma
488 + htab
->sgot
->output_offset
+ got_offset
),
492 if (e
== TLS_GOT_MOD_AND_OFF
|| e
== TLS_GOT_OFF
)
495 if (list
->type
== GOT_TLS_IE
)
497 addend
= bfd_get_32 (output_bfd
,
498 htab
->sgot
->contents
+ got_offset
);
501 ADD_RELA (output_bfd
, got
,
502 got_offset
+ (e
== TLS_GOT_MOD_AND_OFF
? 4 : 0),
504 (list
->type
== GOT_TLS_IE
? R_ARC_TLS_TPOFF
508 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
509 GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = %#lx\n",
512 (long) (htab
->sgot
->output_section
->vma
513 + htab
->sgot
->output_offset
+ got_offset
),
514 (long) dynindx
, (long) addend
);
516 list
->created_dyn_relocation
= TRUE
;
521 create_got_dynrelocs_for_got_info (struct got_entry
**list_p
,
523 struct bfd_link_info
* info
,
524 struct elf_link_hash_entry
*h
)
529 struct got_entry
*list
= *list_p
;
530 /* Traverse the list of got entries for this symbol. */
533 create_got_dynrelocs_for_single_entry (list
, output_bfd
, info
, h
);
538 #undef ADD_SYMBOL_REF_SEC_AND_RELOC
540 #endif /* ARC_GOT_H */