1 /* ARC-specific support for 32-bit ELF
2 Copyright (C) 1994-2016 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. */
44 struct got_entry
*next
;
47 bfd_boolean processed
;
48 bfd_boolean created_dyn_relocation
;
49 enum tls_got_entries existing_entries
;
52 static struct got_entry
**
53 arc_get_local_got_ents (bfd
* abfd
)
55 static struct got_entry
**local_got_ents
= NULL
;
57 if (local_got_ents
== NULL
)
60 Elf_Internal_Shdr
*symtab_hdr
= &((elf_tdata (abfd
))->symtab_hdr
);
62 size
= symtab_hdr
->sh_info
* sizeof (bfd_vma
);
63 local_got_ents
= (struct got_entry
**)
64 bfd_alloc (abfd
, sizeof (struct got_entry
*) * size
);
65 if (local_got_ents
== NULL
)
68 memset (local_got_ents
, 0, sizeof (struct got_entry
*) * size
);
69 elf_local_got_ents (abfd
) = local_got_ents
;
72 return local_got_ents
;
75 static struct got_entry
*
76 got_entry_for_type (struct got_entry
**list
,
79 struct got_entry
**p
= list
;
82 if ((*p
)->type
== type
)
90 new_got_entry_to_list (struct got_entry
**list
,
93 enum tls_got_entries existing_entries
)
95 /* Find list end. Avoid having multiple entries of the same
97 struct got_entry
**p
= list
;
100 if ((*p
)->type
== type
)
105 struct got_entry
*entry
106 = (struct got_entry
*) malloc (sizeof (struct got_entry
));
109 entry
->offset
= offset
;
111 entry
->processed
= FALSE
;
112 entry
->created_dyn_relocation
= FALSE
;
113 entry
->existing_entries
= existing_entries
;
115 ARC_DEBUG ("New GOT got entry added to list: "
116 "type: %d, offset: %d, existing_entries:%d\n",
117 type
, offset
, existing_entries
);
119 /* Add the entry to the end of the list. */
123 static enum tls_type_e
124 tls_type_for_reloc (reloc_howto_type
*howto
)
126 enum tls_type_e ret
= GOT_UNKNOWN
;
127 if (is_reloc_for_GOT (howto
))
133 case R_ARC_TLS_GD_GOT
:
136 case R_ARC_TLS_IE_GOT
:
139 case R_ARC_TLS_LE_32
:
150 static struct got_entry
**
151 get_got_entry_list_for_symbol (bfd
*abfd
,
152 unsigned long r_symndx
,
153 struct elf_link_hash_entry
*h
)
157 return &h
->got
.glist
;
161 struct got_entry
**local_got_ents
162 = arc_get_local_got_ents (abfd
);
163 return &local_got_ents
[r_symndx
];
168 static enum tls_type_e
169 arc_got_entry_type_for_reloc (reloc_howto_type
*howto
)
171 enum tls_type_e type
= GOT_UNKNOWN
;
173 if (is_reloc_for_GOT (howto
))
175 else if (is_reloc_for_TLS (howto
))
179 case R_ARC_TLS_GD_GOT
:
182 case R_ARC_TLS_IE_GOT
:
192 #define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
193 htab->s##SECNAME->size; \
195 if (COND_FOR_RELOC) \
197 htab->srel##SECNAME->size += sizeof (Elf32_External_Rela); \
198 ARC_DEBUG ("arc_info: Added reloc space in " \
199 #SECNAME " section at " __FILE__ \
200 ":%d for symbol %s\n", \
201 __LINE__, name_for_global_symbol (H)); \
204 if (h->dynindx == -1 && !h->forced_local) \
205 if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
207 htab->s##SECNAME->size += 4; \
211 arc_fill_got_info_for_reloc (enum tls_type_e type
,
212 struct got_entry
**list
,
213 struct bfd_link_info
* info
,
214 struct elf_link_hash_entry
*h
)
216 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
218 if (got_entry_for_type (list
, type
) != NULL
)
226 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, bfd_link_pic (info
)
228 new_got_entry_to_list (list
, type
, offset
, TLS_GOT_NONE
);
236 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, TRUE
, h
);
237 bfd_vma ATTRIBUTE_UNUSED notneeded
238 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, TRUE
, h
);
239 new_got_entry_to_list (list
, type
, offset
, TLS_GOT_MOD_AND_OFF
);
246 = ADD_SYMBOL_REF_SEC_AND_RELOC (got
, TRUE
, h
);
247 new_got_entry_to_list (list
, type
, offset
, TLS_GOT_OFF
);
260 relocate_fix_got_relocs_for_got_info (struct got_entry
**list_p
,
261 enum tls_type_e type
,
262 struct bfd_link_info
* info
,
264 unsigned long r_symndx
,
265 Elf_Internal_Sym
*local_syms
,
266 asection
**local_sections
,
267 struct elf_link_hash_entry
*h
,
268 struct arc_relocation_data
*reloc_data
)
271 if (list_p
== NULL
|| type
== GOT_UNKNOWN
|| type
== GOT_TLS_LE
)
274 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
275 struct got_entry
*entry
= NULL
;
277 entry
= got_entry_for_type (list_p
, type
);
281 || (! elf_hash_table (info
)->dynamic_sections_created
282 || (bfd_link_pic (info
)
283 && SYMBOL_REFERENCES_LOCAL (info
, h
))))
285 const char ATTRIBUTE_UNUSED
*symbol_name
;
286 static const char local_name
[] = "(local)";
287 asection
*tls_sec
= NULL
;
288 bfd_vma sym_value
= 0;
292 // TODO: This should not be here.
293 reloc_data
->sym_value
= h
->root
.u
.def
.value
;
294 reloc_data
->sym_section
= h
->root
.u
.def
.section
;
296 sym_value
= h
->root
.u
.def
.value
297 + h
->root
.u
.def
.section
->output_section
->vma
298 + h
->root
.u
.def
.section
->output_offset
;
300 tls_sec
= elf_hash_table (info
)->tls_sec
;
302 symbol_name
= h
->root
.root
.string
;
306 Elf_Internal_Sym
*sym
= local_syms
+ r_symndx
;
307 asection
*sec
= local_sections
[r_symndx
];
309 sym_value
= sym
->st_value
310 + sec
->output_section
->vma
311 + sec
->output_offset
;
313 tls_sec
= elf_hash_table (info
)->tls_sec
;
315 symbol_name
= local_name
;
319 if (entry
&& entry
->processed
== FALSE
)
325 BFD_ASSERT (tls_sec
&& tls_sec
->output_section
);
326 bfd_vma sec_vma
= tls_sec
->output_section
->vma
;
328 bfd_put_32 (output_bfd
,
330 htab
->sgot
->contents
+ entry
->offset
331 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
334 ARC_DEBUG ("arc_info: FIXED -> %s value = 0x%x "
335 "@ 0x%x, for symbol %s\n",
336 (entry
->type
== GOT_TLS_GD
? "GOT_TLS_GD" :
339 htab
->sgot
->contents
+ entry
->offset
340 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
348 BFD_ASSERT (tls_sec
&& tls_sec
->output_section
);
349 bfd_vma ATTRIBUTE_UNUSED sec_vma
350 = tls_sec
->output_section
->vma
;
352 ARC_DEBUG ("arc_info: FIXED -> %s value = 0x%x "
353 "@ 0x%x, for symbol %s\n",
354 (entry
->type
== GOT_TLS_GD
? "GOT_TLS_GD" :
357 htab
->sgot
->contents
+ entry
->offset
358 + (entry
->existing_entries
== TLS_GOT_MOD_AND_OFF
367 = reloc_data
->sym_section
->output_section
->vma
368 + reloc_data
->sym_section
->output_offset
;
370 if (h
->root
.type
!= bfd_link_hash_undefweak
)
372 bfd_put_32 (output_bfd
,
373 reloc_data
->sym_value
+ sec_vma
,
374 htab
->sgot
->contents
+ entry
->offset
);
376 ARC_DEBUG ("arc_info: PATCHED: 0x%08x "
377 "@ 0x%08x for sym %s in got offset 0x%x\n",
378 reloc_data
->sym_value
+ sec_vma
,
379 htab
->sgot
->output_section
->vma
380 + htab
->sgot
->output_offset
+ entry
->offset
,
386 ARC_DEBUG ("arc_info: PATCHED: NOT_PATCHED "
387 "@ 0x%08x for sym %s in got offset 0x%x "
389 htab
->sgot
->output_section
->vma
390 + htab
->sgot
->output_offset
+ entry
->offset
,
400 entry
->processed
= TRUE
;
404 return entry
->offset
;
408 create_got_dynrelocs_for_single_entry (struct got_entry
*list
,
410 struct bfd_link_info
* info
,
411 struct elf_link_hash_entry
*h
)
416 bfd_vma got_offset
= list
->offset
;
418 if (list
->type
== GOT_NORMAL
419 && list
->created_dyn_relocation
== FALSE
)
421 if (bfd_link_pic (info
)
423 && (info
->symbolic
|| h
->dynindx
== -1)
426 ADD_RELA (output_bfd
, got
, got_offset
, 0, R_ARC_RELATIVE
, 0);
428 /* Do not fully understand the side effects of this condition.
429 The relocation space might still being reserved. Perhaps
430 I should clear its value. */
431 else if (h
!= NULL
&& h
->dynindx
!= -1)
433 ADD_RELA (output_bfd
, got
, got_offset
, h
->dynindx
, R_ARC_GLOB_DAT
, 0);
435 list
->created_dyn_relocation
= TRUE
;
437 else if (list
->existing_entries
!= TLS_GOT_NONE
438 && list
->created_dyn_relocation
== FALSE
)
440 /* TODO TLS: This is not called for local symbols.
441 In order to correctly implement TLS, this should also
442 be called for all local symbols with tls got entries.
443 Should be moved to relocate_section in order to make it
444 work for local symbols. */
445 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
446 enum tls_got_entries e
= list
->existing_entries
;
448 BFD_ASSERT (list
->type
!= GOT_TLS_GD
449 || list
->existing_entries
== TLS_GOT_MOD_AND_OFF
);
451 bfd_vma dynindx
= (h
== NULL
|| h
->dynindx
== -1) ? 0 : h
->dynindx
;
453 if (e
== TLS_GOT_MOD_AND_OFF
|| e
== TLS_GOT_MOD
)
455 ADD_RELA (output_bfd
, got
, got_offset
, dynindx
,
456 R_ARC_TLS_DTPMOD
, 0);
457 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
458 GOT_OFFSET = 0x%x, GOT_VMA = 0x%x, INDEX = %d, ADDEND = 0x%x\n",
461 htab
->sgot
->output_section
->vma
462 + htab
->sgot
->output_offset
+ got_offset
,
465 if (e
== TLS_GOT_MOD_AND_OFF
|| e
== TLS_GOT_OFF
)
468 if (list
->type
== GOT_TLS_IE
)
469 addend
= bfd_get_32 (output_bfd
,
470 htab
->sgot
->contents
+ got_offset
);
472 ADD_RELA (output_bfd
, got
,
473 got_offset
+ (e
== TLS_GOT_MOD_AND_OFF
? 4 : 0),
475 (list
->type
== GOT_TLS_IE
? R_ARC_TLS_TPOFF
479 ARC_DEBUG ("arc_info: TLS_DYNRELOC: type = %d, \
480 GOT_OFFSET = 0x%x, GOT_VMA = 0x%x, INDEX = %d, ADDEND = 0x%x\n",
483 htab
->sgot
->output_section
->vma
484 + htab
->sgot
->output_offset
+ got_offset
,
487 list
->created_dyn_relocation
= TRUE
;
492 create_got_dynrelocs_for_got_info (struct got_entry
**list_p
,
494 struct bfd_link_info
* info
,
495 struct elf_link_hash_entry
*h
)
500 struct got_entry
*list
= *list_p
;
501 /* Traverse the list of got entries for this symbol. */
504 create_got_dynrelocs_for_single_entry (list
, output_bfd
, info
, h
);
509 #undef ADD_SYMBOL_REF_SEC_AND_RELOC
511 #endif /* ARC_GOT_H */