1 /* LoongArch-specific support for NN-bit ELF.
2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
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; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
28 #include "elf/loongarch.h"
29 #include "elfxx-loongarch.h"
32 loongarch_info_to_howto_rela (bfd
*abfd
, arelent
*cache_ptr
,
33 Elf_Internal_Rela
*dst
)
35 cache_ptr
->howto
= loongarch_elf_rtype_to_howto (abfd
,
36 ELFNN_R_TYPE (dst
->r_info
));
37 return cache_ptr
->howto
!= NULL
;
40 /* LoongArch ELF linker hash entry. */
41 struct loongarch_elf_link_hash_entry
43 struct elf_link_hash_entry elf
;
53 #define loongarch_elf_hash_entry(ent) \
54 ((struct loongarch_elf_link_hash_entry *) (ent))
56 struct _bfd_loongarch_elf_obj_tdata
58 struct elf_obj_tdata root
;
60 /* The tls_type for each local got entry. */
61 char *local_got_tls_type
;
64 #define _bfd_loongarch_elf_tdata(abfd) \
65 ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
67 #define _bfd_loongarch_elf_local_got_tls_type(abfd) \
68 (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
70 #define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
72 ? &loongarch_elf_hash_entry (h)->tls_type \
73 : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
75 #define is_loongarch_elf(bfd) \
76 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
77 && elf_tdata (bfd) != NULL \
78 && elf_object_id (bfd) == LARCH_ELF_DATA)
80 struct loongarch_elf_link_hash_table
82 struct elf_link_hash_table elf
;
84 /* Short-cuts to get to dynamic linker sections. */
87 /* Small local sym to section mapping cache. */
88 struct sym_cache sym_cache
;
90 /* Used by local STT_GNU_IFUNC symbols. */
91 htab_t loc_hash_table
;
92 void *loc_hash_memory
;
94 /* The max alignment of output sections. */
95 bfd_vma max_alignment
;
98 /* Get the LoongArch ELF linker hash table from a link_info structure. */
99 #define loongarch_elf_hash_table(p) \
100 (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
101 ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
104 #define MINUS_ONE ((bfd_vma) 0 - 1)
106 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
108 #define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
109 #define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
111 #define PLT_HEADER_INSNS 8
112 #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
114 #define PLT_ENTRY_INSNS 4
115 #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
117 #define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
119 #define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
121 #define elf_backend_want_got_plt 1
123 #define elf_backend_plt_readonly 1
125 #define elf_backend_want_plt_sym 1
126 #define elf_backend_plt_alignment 4
127 #define elf_backend_can_gc_sections 1
128 #define elf_backend_can_refcount 1
129 #define elf_backend_want_got_sym 1
131 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
133 #define elf_backend_want_dynrelro 1
134 #define elf_backend_rela_normal 1
135 #define elf_backend_default_execstack 0
137 /* Generate a PLT header. */
140 loongarch_make_plt_header (bfd_vma got_plt_addr
, bfd_vma plt_header_addr
,
143 bfd_vma pcrel
= got_plt_addr
- plt_header_addr
;
146 if (pcrel
+ 0x80000800 > 0xffffffff)
148 _bfd_error_handler (_("%#" PRIx64
" invaild imm"), (uint64_t) pcrel
);
149 bfd_set_error (bfd_error_bad_value
);
152 hi
= ((pcrel
+ 0x800) >> 12) & 0xfffff;
155 /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
156 sub.[wd] $t1, $t1, $t3
157 ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
158 addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
159 addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
160 srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
161 ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
164 if (GOT_ENTRY_SIZE
== 8)
166 entry
[0] = 0x1c00000e | (hi
& 0xfffff) << 5;
167 entry
[1] = 0x0011bdad;
168 entry
[2] = 0x28c001cf | (lo
& 0xfff) << 10;
169 entry
[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE
+ 12)) & 0xfff) << 10;
170 entry
[4] = 0x02c001cc | (lo
& 0xfff) << 10;
171 entry
[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES
) << 10;
172 entry
[6] = 0x28c0018c | GOT_ENTRY_SIZE
<< 10;
173 entry
[7] = 0x4c0001e0;
177 entry
[0] = 0x1c00000e | (hi
& 0xfffff) << 5;
178 entry
[1] = 0x00113dad;
179 entry
[2] = 0x288001cf | (lo
& 0xfff) << 10;
180 entry
[3] = 0x028001ad | ((-(PLT_HEADER_SIZE
+ 12)) & 0xfff) << 10;
181 entry
[4] = 0x028001cc | (lo
& 0xfff) << 10;
182 entry
[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES
) << 10;
183 entry
[6] = 0x2880018c | GOT_ENTRY_SIZE
<< 10;
184 entry
[7] = 0x4c0001e0;
189 /* Generate a PLT entry. */
192 loongarch_make_plt_entry (bfd_vma got_plt_entry_addr
, bfd_vma plt_entry_addr
,
195 bfd_vma pcrel
= got_plt_entry_addr
- plt_entry_addr
;
198 if (pcrel
+ 0x80000800 > 0xffffffff)
200 _bfd_error_handler (_("%#" PRIx64
" invaild imm"), (uint64_t) pcrel
);
201 bfd_set_error (bfd_error_bad_value
);
204 hi
= ((pcrel
+ 0x800) >> 12) & 0xfffff;
207 entry
[0] = 0x1c00000f | (hi
& 0xfffff) << 5;
208 entry
[1] = ((GOT_ENTRY_SIZE
== 8 ? 0x28c001ef : 0x288001ef)
209 | (lo
& 0xfff) << 10);
210 entry
[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
211 entry
[3] = 0x03400000; /* nop */
216 /* Create an entry in an LoongArch ELF linker hash table. */
218 static struct bfd_hash_entry
*
219 link_hash_newfunc (struct bfd_hash_entry
*entry
, struct bfd_hash_table
*table
,
222 struct loongarch_elf_link_hash_entry
*eh
;
224 /* Allocate the structure if it has not already been allocated by a
228 entry
= bfd_hash_allocate (table
, sizeof (*eh
));
233 /* Call the allocation method of the superclass. */
234 entry
= _bfd_elf_link_hash_newfunc (entry
, table
, string
);
237 eh
= (struct loongarch_elf_link_hash_entry
*) entry
;
238 eh
->tls_type
= GOT_UNKNOWN
;
244 /* Compute a hash of a local hash entry. We use elf_link_hash_entry
245 for local symbol so that we can handle local STT_GNU_IFUNC symbols
246 as global symbol. We reuse indx and dynstr_index for local symbol
247 hash since they aren't used by global symbols in this backend. */
250 elfNN_loongarch_local_htab_hash (const void *ptr
)
252 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) ptr
;
253 return ELF_LOCAL_SYMBOL_HASH (h
->indx
, h
->dynstr_index
);
256 /* Compare local hash entries. */
259 elfNN_loongarch_local_htab_eq (const void *ptr1
, const void *ptr2
)
261 struct elf_link_hash_entry
*h1
= (struct elf_link_hash_entry
*) ptr1
;
262 struct elf_link_hash_entry
*h2
= (struct elf_link_hash_entry
*) ptr2
;
264 return h1
->indx
== h2
->indx
&& h1
->dynstr_index
== h2
->dynstr_index
;
267 /* Find and/or create a hash entry for local symbol. */
268 static struct elf_link_hash_entry
*
269 elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table
*htab
,
270 bfd
*abfd
, const Elf_Internal_Rela
*rel
,
273 struct loongarch_elf_link_hash_entry e
, *ret
;
274 asection
*sec
= abfd
->sections
;
275 hashval_t h
= ELF_LOCAL_SYMBOL_HASH (sec
->id
, ELFNN_R_SYM (rel
->r_info
));
278 e
.elf
.indx
= sec
->id
;
279 e
.elf
.dynstr_index
= ELFNN_R_SYM (rel
->r_info
);
280 slot
= htab_find_slot_with_hash (htab
->loc_hash_table
, &e
, h
,
281 create
? INSERT
: NO_INSERT
);
288 ret
= (struct loongarch_elf_link_hash_entry
*) *slot
;
292 ret
= ((struct loongarch_elf_link_hash_entry
*)
293 objalloc_alloc ((struct objalloc
*) htab
->loc_hash_memory
,
294 sizeof (struct loongarch_elf_link_hash_entry
)));
297 memset (ret
, 0, sizeof (*ret
));
298 ret
->elf
.indx
= sec
->id
;
299 ret
->elf
.pointer_equality_needed
= 0;
300 ret
->elf
.dynstr_index
= ELFNN_R_SYM (rel
->r_info
);
301 ret
->elf
.dynindx
= -1;
302 ret
->elf
.needs_plt
= 0;
303 ret
->elf
.plt
.refcount
= -1;
304 ret
->elf
.got
.refcount
= -1;
305 ret
->elf
.def_dynamic
= 0;
306 ret
->elf
.def_regular
= 1;
307 ret
->elf
.ref_dynamic
= 0; /* This should be always 0 for local. */
308 ret
->elf
.ref_regular
= 0;
309 ret
->elf
.forced_local
= 1;
310 ret
->elf
.root
.type
= bfd_link_hash_defined
;
316 /* Destroy an LoongArch elf linker hash table. */
319 elfNN_loongarch_link_hash_table_free (bfd
*obfd
)
321 struct loongarch_elf_link_hash_table
*ret
;
322 ret
= (struct loongarch_elf_link_hash_table
*) obfd
->link
.hash
;
324 if (ret
->loc_hash_table
)
325 htab_delete (ret
->loc_hash_table
);
326 if (ret
->loc_hash_memory
)
327 objalloc_free ((struct objalloc
*) ret
->loc_hash_memory
);
329 _bfd_elf_link_hash_table_free (obfd
);
332 /* Create a LoongArch ELF linker hash table. */
334 static struct bfd_link_hash_table
*
335 loongarch_elf_link_hash_table_create (bfd
*abfd
)
337 struct loongarch_elf_link_hash_table
*ret
;
338 bfd_size_type amt
= sizeof (struct loongarch_elf_link_hash_table
);
340 ret
= (struct loongarch_elf_link_hash_table
*) bfd_zmalloc (amt
);
344 if (!_bfd_elf_link_hash_table_init
345 (&ret
->elf
, abfd
, link_hash_newfunc
,
346 sizeof (struct loongarch_elf_link_hash_entry
), LARCH_ELF_DATA
))
352 ret
->max_alignment
= MINUS_ONE
;
354 ret
->loc_hash_table
= htab_try_create (1024, elfNN_loongarch_local_htab_hash
,
355 elfNN_loongarch_local_htab_eq
, NULL
);
356 ret
->loc_hash_memory
= objalloc_create ();
357 if (!ret
->loc_hash_table
|| !ret
->loc_hash_memory
)
359 elfNN_loongarch_link_hash_table_free (abfd
);
362 ret
->elf
.root
.hash_table_free
= elfNN_loongarch_link_hash_table_free
;
364 return &ret
->elf
.root
;
367 /* Merge backend specific data from an object file to the output
368 object file when linking. */
371 elfNN_loongarch_merge_private_bfd_data (bfd
*ibfd
, struct bfd_link_info
*info
)
373 bfd
*obfd
= info
->output_bfd
;
374 flagword in_flags
= elf_elfheader (ibfd
)->e_flags
;
375 flagword out_flags
= elf_elfheader (obfd
)->e_flags
;
377 if (!is_loongarch_elf (ibfd
) || !is_loongarch_elf (obfd
))
380 if (strcmp (bfd_get_target (ibfd
), bfd_get_target (obfd
)) != 0)
382 _bfd_error_handler (_("%pB: ABI is incompatible with that of "
383 "the selected emulation:\n"
384 " target emulation `%s' does not match `%s'"),
385 ibfd
, bfd_get_target (ibfd
), bfd_get_target (obfd
));
389 if (!_bfd_elf_merge_object_attributes (ibfd
, info
))
392 /* If the input BFD is not a dynamic object and it does not contain any
393 non-data sections, do not account its ABI. For example, various
394 packages produces such data-only relocatable objects with
395 `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
396 But they are compatible with all ABIs. */
397 if (!(ibfd
->flags
& DYNAMIC
))
400 bool have_code_sections
= false;
401 for (sec
= ibfd
->sections
; sec
!= NULL
; sec
= sec
->next
)
402 if ((bfd_section_flags (sec
)
403 & (SEC_LOAD
| SEC_CODE
| SEC_HAS_CONTENTS
))
404 == (SEC_LOAD
| SEC_CODE
| SEC_HAS_CONTENTS
))
406 have_code_sections
= true;
409 if (!have_code_sections
)
413 if (!elf_flags_init (obfd
))
415 elf_flags_init (obfd
) = true;
416 elf_elfheader (obfd
)->e_flags
= in_flags
;
419 else if (out_flags
!= in_flags
)
421 if ((EF_LOONGARCH_IS_OBJ_V0 (out_flags
)
422 && EF_LOONGARCH_IS_OBJ_V1 (in_flags
))
423 || (EF_LOONGARCH_IS_OBJ_V0 (in_flags
)
424 && EF_LOONGARCH_IS_OBJ_V1 (out_flags
)))
426 elf_elfheader (obfd
)->e_flags
|= EF_LOONGARCH_OBJABI_V1
;
427 out_flags
= elf_elfheader (obfd
)->e_flags
;
428 in_flags
= out_flags
;
432 /* Disallow linking different ABIs. */
433 /* Only check relocation version.
434 The obj_v0 is compatible with obj_v1. */
435 if (EF_LOONGARCH_ABI(out_flags
^ in_flags
) & EF_LOONGARCH_ABI_MASK
)
437 _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd
);
444 bfd_set_error (bfd_error_bad_value
);
448 /* Create the .got section. */
451 loongarch_elf_create_got_section (bfd
*abfd
, struct bfd_link_info
*info
)
456 struct elf_link_hash_entry
*h
;
457 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
458 struct elf_link_hash_table
*htab
= elf_hash_table (info
);
460 /* This function may be called more than once. */
461 if (htab
->sgot
!= NULL
)
464 flags
= bed
->dynamic_sec_flags
;
465 name
= bed
->rela_plts_and_copies_p
? ".rela.got" : ".rel.got";
466 s
= bfd_make_section_anyway_with_flags (abfd
, name
, flags
| SEC_READONLY
);
468 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
472 s
= s_got
= bfd_make_section_anyway_with_flags (abfd
, ".got", flags
);
473 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
477 /* The first bit of the global offset table is the header. */
478 s
->size
+= bed
->got_header_size
;
480 if (bed
->want_got_plt
)
482 s
= bfd_make_section_anyway_with_flags (abfd
, ".got.plt", flags
);
483 if (s
== NULL
|| !bfd_set_section_alignment (s
, bed
->s
->log_file_align
))
487 /* Reserve room for the header. */
488 s
->size
= GOTPLT_HEADER_SIZE
;
491 if (bed
->want_got_sym
)
493 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
494 section. We don't do this in the linker script because we don't want
495 to define the symbol if we are not creating a global offset table. */
496 h
= _bfd_elf_define_linkage_sym (abfd
, info
, s_got
,
497 "_GLOBAL_OFFSET_TABLE_");
498 elf_hash_table (info
)->hgot
= h
;
505 /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
506 .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
510 loongarch_elf_create_dynamic_sections (bfd
*dynobj
, struct bfd_link_info
*info
)
512 struct loongarch_elf_link_hash_table
*htab
;
514 htab
= loongarch_elf_hash_table (info
);
515 BFD_ASSERT (htab
!= NULL
);
517 if (!loongarch_elf_create_got_section (dynobj
, info
))
520 if (!_bfd_elf_create_dynamic_sections (dynobj
, info
))
523 if (!bfd_link_pic (info
))
525 = bfd_make_section_anyway_with_flags (dynobj
, ".tdata.dyn",
526 SEC_ALLOC
| SEC_THREAD_LOCAL
);
528 if (!htab
->elf
.splt
|| !htab
->elf
.srelplt
|| !htab
->elf
.sdynbss
529 || (!bfd_link_pic (info
) && (!htab
->elf
.srelbss
|| !htab
->sdyntdata
)))
536 loongarch_elf_record_tls_and_got_reference (bfd
*abfd
,
537 struct bfd_link_info
*info
,
538 struct elf_link_hash_entry
*h
,
539 unsigned long symndx
,
542 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
543 Elf_Internal_Shdr
*symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
545 /* This is a global offset table entry for a local symbol. */
546 if (elf_local_got_refcounts (abfd
) == NULL
)
549 symtab_hdr
->sh_info
* (sizeof (bfd_vma
) + sizeof (tls_type
));
550 if (!(elf_local_got_refcounts (abfd
) = bfd_zalloc (abfd
, size
)))
552 _bfd_loongarch_elf_local_got_tls_type (abfd
) =
553 (char *) (elf_local_got_refcounts (abfd
) + symtab_hdr
->sh_info
);
562 if (htab
->elf
.sgot
== NULL
563 && !loongarch_elf_create_got_section (htab
->elf
.dynobj
, info
))
567 if (h
->got
.refcount
< 0)
572 elf_local_got_refcounts (abfd
)[symndx
]++;
575 /* No need for GOT. */
578 _bfd_error_handler (_("Internal error: unreachable."));
582 char *new_tls_type
= &_bfd_loongarch_elf_tls_type (abfd
, h
, symndx
);
583 *new_tls_type
|= tls_type
;
584 if ((*new_tls_type
& GOT_NORMAL
) && (*new_tls_type
& ~GOT_NORMAL
))
586 _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
587 "thread local symbol"),
589 h
? h
->root
.root
.string
: "<local>");
596 /* Look through the relocs for a section during the first phase, and
597 allocate space in the global offset table or procedure linkage
601 loongarch_elf_check_relocs (bfd
*abfd
, struct bfd_link_info
*info
,
602 asection
*sec
, const Elf_Internal_Rela
*relocs
)
604 struct loongarch_elf_link_hash_table
*htab
;
605 Elf_Internal_Shdr
*symtab_hdr
;
606 struct elf_link_hash_entry
**sym_hashes
;
607 const Elf_Internal_Rela
*rel
;
608 asection
*sreloc
= NULL
;
610 if (bfd_link_relocatable (info
))
613 htab
= loongarch_elf_hash_table (info
);
614 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
615 sym_hashes
= elf_sym_hashes (abfd
);
617 if (htab
->elf
.dynobj
== NULL
)
618 htab
->elf
.dynobj
= abfd
;
620 for (rel
= relocs
; rel
< relocs
+ sec
->reloc_count
; rel
++)
623 unsigned int r_symndx
;
624 struct elf_link_hash_entry
*h
;
625 Elf_Internal_Sym
*isym
= NULL
;
627 r_symndx
= ELFNN_R_SYM (rel
->r_info
);
628 r_type
= ELFNN_R_TYPE (rel
->r_info
);
630 if (r_symndx
>= NUM_SHDR_ENTRIES (symtab_hdr
))
632 _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd
, r_symndx
);
636 if (r_symndx
< symtab_hdr
->sh_info
)
638 /* A local symbol. */
639 isym
= bfd_sym_from_r_symndx (&htab
->elf
.sym_cache
, abfd
, r_symndx
);
643 if (ELF_ST_TYPE (isym
->st_info
) == STT_GNU_IFUNC
)
645 h
= elfNN_loongarch_get_local_sym_hash (htab
, abfd
, rel
, true);
649 h
->type
= STT_GNU_IFUNC
;
657 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
658 while (h
->root
.type
== bfd_link_hash_indirect
659 || h
->root
.type
== bfd_link_hash_warning
)
660 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
663 /* It is referenced by a non-shared object. */
667 if (h
&& h
->type
== STT_GNU_IFUNC
)
669 if (htab
->elf
.dynobj
== NULL
)
670 htab
->elf
.dynobj
= abfd
;
672 /* Create 'irelifunc' in PIC object. */
673 if (bfd_link_pic (info
)
674 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
676 /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
677 else if (!htab
->elf
.splt
678 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
680 /* Create the ifunc sections, iplt and ipltgot, for static
682 if ((r_type
== R_LARCH_64
|| r_type
== R_LARCH_32
)
683 && !_bfd_elf_create_ifunc_sections (htab
->elf
.dynobj
, info
))
686 if (h
->plt
.refcount
< 0)
691 elf_tdata (info
->output_bfd
)->has_gnu_osabi
|= elf_gnu_osabi_ifunc
;
694 int need_dynreloc
= 0;
695 int only_need_pcrel
= 0;
699 case R_LARCH_GOT_PC_HI20
:
700 case R_LARCH_GOT_HI20
:
701 case R_LARCH_SOP_PUSH_GPREL
:
704 h
->pointer_equality_needed
= 1;
705 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
711 case R_LARCH_TLS_LD_PC_HI20
:
712 case R_LARCH_TLS_LD_HI20
:
713 case R_LARCH_TLS_GD_PC_HI20
:
714 case R_LARCH_TLS_GD_HI20
:
715 case R_LARCH_SOP_PUSH_TLS_GD
:
716 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
722 case R_LARCH_TLS_IE_PC_HI20
:
723 case R_LARCH_TLS_IE_HI20
:
724 case R_LARCH_SOP_PUSH_TLS_GOT
:
725 if (bfd_link_pic (info
))
726 /* May fail for lazy-bind. */
727 info
->flags
|= DF_STATIC_TLS
;
729 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
735 case R_LARCH_TLS_LE_HI20
:
736 case R_LARCH_SOP_PUSH_TLS_TPREL
:
737 if (!bfd_link_executable (info
))
740 info
->flags
|= DF_STATIC_TLS
;
742 if (!loongarch_elf_record_tls_and_got_reference (abfd
, info
, h
,
748 case R_LARCH_ABS_HI20
:
749 case R_LARCH_SOP_PUSH_ABSOLUTE
:
751 /* If this reloc is in a read-only section, we might
752 need a copy reloc. We can't check reliably at this
753 stage whether the section is read-only, as input
754 sections have not yet been mapped to output sections.
755 Tentatively set the flag for now, and correct in
756 adjust_dynamic_symbol. */
760 case R_LARCH_PCALA_HI20
:
763 /* For pcalau12i + jirl. */
765 if (h
->plt
.refcount
< 0)
770 h
->pointer_equality_needed
= 1;
781 if (!bfd_link_pic (info
))
784 /* We try to create PLT stub for all non-local function. */
785 if (h
->plt
.refcount
< 0)
792 case R_LARCH_SOP_PUSH_PCREL
:
795 if (!bfd_link_pic (info
))
798 /* We try to create PLT stub for all non-local function. */
799 if (h
->plt
.refcount
< 0)
802 h
->pointer_equality_needed
= 1;
807 case R_LARCH_SOP_PUSH_PLT_PCREL
:
808 /* This symbol requires a procedure linkage table entry. We
809 actually build the entry in adjust_dynamic_symbol,
810 because this might be a case of linking PIC code without
811 linking in any dynamic objects, in which case we don't
812 need to generate a procedure linkage table after all. */
816 if (h
->plt
.refcount
< 0)
822 case R_LARCH_TLS_DTPREL32
:
823 case R_LARCH_TLS_DTPREL64
:
828 case R_LARCH_JUMP_SLOT
:
834 /* If resolved symbol is defined in this object,
835 1. Under pie, the symbol is known. We convert it
836 into R_LARCH_RELATIVE and need load-addr still.
837 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
838 3. Under dll, R_LARCH_NN can't be changed normally, since
839 its defination could be covered by the one in executable.
840 For symbolic, we convert it into R_LARCH_RELATIVE.
841 Thus, only under pde, it needs pcrel only. We discard it. */
842 only_need_pcrel
= bfd_link_pde (info
);
845 && (!bfd_link_pic (info
)
846 || h
->type
== STT_GNU_IFUNC
))
848 /* This reloc might not bind locally. */
850 h
->pointer_equality_needed
= 1;
853 || (sec
->flags
& (SEC_CODE
| SEC_READONLY
)) != 0)
855 /* We may need a .plt entry if the symbol is a function
856 defined in a shared lib or is a function referenced
857 from the code or read-only section. */
858 h
->plt
.refcount
+= 1;
863 case R_LARCH_GNU_VTINHERIT
:
864 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
868 case R_LARCH_GNU_VTENTRY
:
869 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
877 /* Record some info for sizing and allocating dynamic entry. */
878 if (need_dynreloc
&& (sec
->flags
& SEC_ALLOC
))
880 /* When creating a shared object, we must copy these
881 relocs into the output file. We create a reloc
882 section in dynobj and make room for the reloc. */
883 struct elf_dyn_relocs
*p
;
884 struct elf_dyn_relocs
**head
;
889 = _bfd_elf_make_dynamic_reloc_section (sec
, htab
->elf
.dynobj
,
890 LARCH_ELF_LOG_WORD_BYTES
,
891 abfd
, /*rela?*/ true);
896 /* If this is a global symbol, we count the number of
897 relocations we need for this symbol. */
899 head
= &h
->dyn_relocs
;
902 /* Track dynamic relocs needed for local syms too.
903 We really need local syms available to do this
909 s
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
913 vpp
= &elf_section_data (s
)->local_dynrel
;
914 head
= (struct elf_dyn_relocs
**) vpp
;
918 if (p
== NULL
|| p
->sec
!= sec
)
920 bfd_size_type amt
= sizeof *p
;
921 p
= (struct elf_dyn_relocs
*) bfd_alloc (htab
->elf
.dynobj
, amt
);
932 p
->pc_count
+= only_need_pcrel
;
939 /* Find dynamic relocs for H that apply to read-only sections. */
942 readonly_dynrelocs (struct elf_link_hash_entry
*h
)
944 struct elf_dyn_relocs
*p
;
946 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
948 asection
*s
= p
->sec
->output_section
;
950 if (s
!= NULL
&& (s
->flags
& SEC_READONLY
) != 0)
956 /* Adjust a symbol defined by a dynamic object and referenced by a
957 regular object. The current definition is in some section of the
958 dynamic object, but we're not including those sections. We have to
959 change the definition to something the rest of the link can
962 loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info
*info
,
963 struct elf_link_hash_entry
*h
)
965 struct loongarch_elf_link_hash_table
*htab
;
968 htab
= loongarch_elf_hash_table (info
);
969 BFD_ASSERT (htab
!= NULL
);
971 dynobj
= htab
->elf
.dynobj
;
973 /* Make sure we know what is going on here. */
974 BFD_ASSERT (dynobj
!= NULL
975 && (h
->needs_plt
|| h
->type
== STT_GNU_IFUNC
|| h
->is_weakalias
976 || (h
->def_dynamic
&& h
->ref_regular
&& !h
->def_regular
)));
978 /* If this is a function, put it in the procedure linkage table. We
979 will fill in the contents of the procedure linkage table later
980 (although we could actually do it here). */
981 if (h
->type
== STT_FUNC
|| h
->type
== STT_GNU_IFUNC
|| h
->needs_plt
)
983 if (h
->plt
.refcount
< 0
984 || (h
->type
!= STT_GNU_IFUNC
985 && (SYMBOL_REFERENCES_LOCAL (info
, h
)
986 || (ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
987 && h
->root
.type
== bfd_link_hash_undefweak
))))
989 /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
990 in an input file, but the symbol was never referred to by a
991 dynamic object, or if all references were garbage collected.
992 In such a case, we don't actually need to build a PLT entry. */
993 h
->plt
.offset
= MINUS_ONE
;
1002 h
->plt
.offset
= MINUS_ONE
;
1004 /* If this is a weak symbol, and there is a real definition, the
1005 processor independent code will have arranged for us to see the
1006 real definition first, and we can just use the same value. */
1007 if (h
->is_weakalias
)
1009 struct elf_link_hash_entry
*def
= weakdef (h
);
1010 BFD_ASSERT (def
->root
.type
== bfd_link_hash_defined
);
1011 h
->root
.u
.def
.section
= def
->root
.u
.def
.section
;
1012 h
->root
.u
.def
.value
= def
->root
.u
.def
.value
;
1016 /* R_LARCH_COPY is not adept glibc, not to generate. */
1017 /* Can not print anything, because make check ld. */
1021 /* Allocate space in .plt, .got and associated reloc sections for
1025 allocate_dynrelocs (struct elf_link_hash_entry
*h
, void *inf
)
1027 struct bfd_link_info
*info
;
1028 struct loongarch_elf_link_hash_table
*htab
;
1029 struct elf_dyn_relocs
*p
;
1031 if (h
->root
.type
== bfd_link_hash_indirect
)
1034 if (h
->type
== STT_GNU_IFUNC
1038 info
= (struct bfd_link_info
*) inf
;
1039 htab
= loongarch_elf_hash_table (info
);
1040 bool dyn
= htab
->elf
.dynamic_sections_created
;
1041 BFD_ASSERT (htab
!= NULL
);
1045 asection
*plt
, *gotplt
, *relplt
;
1054 if (h
->dynindx
== -1 && !h
->forced_local
&& dyn
1055 && h
->root
.type
== bfd_link_hash_undefweak
)
1057 if (!bfd_elf_link_record_dynamic_symbol (info
, h
))
1061 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info
), h
)
1062 && h
->type
!= STT_GNU_IFUNC
)
1065 plt
= htab
->elf
.splt
;
1066 gotplt
= htab
->elf
.sgotplt
;
1067 relplt
= htab
->elf
.srelplt
;
1069 else if (htab
->elf
.iplt
)
1071 /* .iplt only for IFUNC. */
1072 if (h
->type
!= STT_GNU_IFUNC
)
1075 plt
= htab
->elf
.iplt
;
1076 gotplt
= htab
->elf
.igotplt
;
1077 relplt
= htab
->elf
.irelplt
;
1083 plt
->size
= PLT_HEADER_SIZE
;
1085 h
->plt
.offset
= plt
->size
;
1086 plt
->size
+= PLT_ENTRY_SIZE
;
1087 gotplt
->size
+= GOT_ENTRY_SIZE
;
1088 relplt
->size
+= sizeof (ElfNN_External_Rela
);
1090 /* If this symbol is not defined in a regular file, and we are
1091 not generating a shared library, then set the symbol to this
1092 location in the .plt. This is required to make function
1093 pointers compare as equal between the normal executable and
1094 the shared library. */
1095 if (!bfd_link_pic (info
)
1098 h
->root
.u
.def
.section
= plt
;
1099 h
->root
.u
.def
.value
= h
->plt
.offset
;
1107 h
->plt
.offset
= MINUS_ONE
;
1109 if (0 < h
->got
.refcount
)
1112 int tls_type
= loongarch_elf_hash_entry (h
)->tls_type
;
1114 /* Make sure this symbol is output as a dynamic symbol.
1115 Undefined weak syms won't yet be marked as dynamic. */
1116 if (h
->dynindx
== -1 && !h
->forced_local
&& dyn
1117 && h
->root
.type
== bfd_link_hash_undefweak
)
1119 if (!bfd_elf_link_record_dynamic_symbol (info
, h
))
1124 h
->got
.offset
= s
->size
;
1125 if (tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
1127 /* TLS_GD needs two dynamic relocs and two GOT slots. */
1128 if (tls_type
& GOT_TLS_GD
)
1130 s
->size
+= 2 * GOT_ENTRY_SIZE
;
1131 if (bfd_link_executable (info
))
1133 /* Link exe and not defined local. */
1134 if (!SYMBOL_REFERENCES_LOCAL (info
, h
))
1135 htab
->elf
.srelgot
->size
+= 2 * sizeof (ElfNN_External_Rela
);
1139 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
1140 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1142 htab
->elf
.srelgot
->size
+= 2 * sizeof (ElfNN_External_Rela
);
1146 /* TLS_IE needs one dynamic reloc and one GOT slot. */
1147 if (tls_type
& GOT_TLS_IE
)
1149 s
->size
+= GOT_ENTRY_SIZE
;
1151 if (bfd_link_executable (info
))
1153 /* Link exe and not defined local. */
1154 if (!SYMBOL_REFERENCES_LOCAL (info
, h
))
1155 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1159 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1165 s
->size
+= GOT_ENTRY_SIZE
;
1166 if ((ELF_ST_VISIBILITY (h
->other
) == STV_DEFAULT
1167 || h
->root
.type
!= bfd_link_hash_undefweak
)
1168 && (bfd_link_pic (info
)
1169 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn
, bfd_link_pic (info
),
1171 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
1172 /* Undefined weak symbol in static PIE resolves to 0 without
1173 any dynamic relocations. */
1174 htab
->elf
.srelgot
->size
+= sizeof (ElfNN_External_Rela
);
1178 h
->got
.offset
= MINUS_ONE
;
1180 if (h
->dyn_relocs
== NULL
)
1183 /* Extra dynamic relocate,
1185 * R_LARCH_TLS_DTPRELNN
1189 if (SYMBOL_CALLS_LOCAL (info
, h
))
1191 struct elf_dyn_relocs
**pp
;
1193 for (pp
= &h
->dyn_relocs
; (p
= *pp
) != NULL
;)
1195 p
->count
-= p
->pc_count
;
1204 if (h
->root
.type
== bfd_link_hash_undefweak
)
1206 if (UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
)
1207 || ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
1208 || (!bfd_link_pic (info
) && h
->non_got_ref
))
1209 h
->dyn_relocs
= NULL
;
1210 else if (h
->dynindx
== -1 && !h
->forced_local
)
1212 /* Make sure this symbol is output as a dynamic symbol.
1213 Undefined weak syms won't yet be marked as dynamic. */
1214 if (!bfd_elf_link_record_dynamic_symbol (info
, h
))
1217 if (h
->dynindx
== -1)
1218 h
->dyn_relocs
= NULL
;
1222 for (p
= h
->dyn_relocs
; p
!= NULL
; p
= p
->next
)
1224 asection
*sreloc
= elf_section_data (p
->sec
)->sreloc
;
1225 sreloc
->size
+= p
->count
* sizeof (ElfNN_External_Rela
);
1231 /* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
1232 For local def and ref ifunc,
1233 dynamic relocations are stored in
1234 1. rela.srelgot section in dynamic object (dll or exec).
1235 2. rela.irelplt section in static executable.
1236 Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
1237 instead of rela.srelplt. Glibc ELF loader will not support
1238 R_LARCH_IRELATIVE relocation in rela.plt. */
1241 local_allocate_ifunc_dyn_relocs (struct bfd_link_info
*info
,
1242 struct elf_link_hash_entry
*h
,
1243 struct elf_dyn_relocs
**head
,
1244 unsigned int plt_entry_size
,
1245 unsigned int plt_header_size
,
1246 unsigned int got_entry_size
,
1249 asection
*plt
, *gotplt
, *relplt
;
1250 struct elf_dyn_relocs
*p
;
1251 unsigned int sizeof_reloc
;
1252 const struct elf_backend_data
*bed
;
1253 struct elf_link_hash_table
*htab
;
1254 /* If AVOID_PLT is TRUE, don't use PLT if possible. */
1255 bool use_plt
= !avoid_plt
|| h
->plt
.refcount
> 0;
1256 bool need_dynreloc
= !use_plt
|| bfd_link_pic (info
);
1258 /* When a PIC object references a STT_GNU_IFUNC symbol defined
1259 in executable or it isn't referenced via PLT, the address of
1260 the resolved function may be used. But in non-PIC executable,
1261 the address of its plt slot may be used. Pointer equality may
1262 not work correctly. PIE or non-PLT reference should be used if
1263 pointer equality is required here.
1265 If STT_GNU_IFUNC symbol is defined in position-dependent executable,
1266 backend should change it to the normal function and set its address
1267 to its PLT entry which should be resolved by R_*_IRELATIVE at
1268 run-time. All external references should be resolved to its PLT in
1271 && !(bfd_link_pde (info
) && h
->def_regular
)
1272 && (h
->dynindx
!= -1
1273 || info
->export_dynamic
)
1274 && h
->pointer_equality_needed
)
1276 info
->callbacks
->einfo
1277 /* xgettext:c-format. */
1278 (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
1279 "equality in `%pB' can not be used when making an "
1280 "executable; recompile with -fPIE and relink with -pie\n"),
1281 h
->root
.root
.string
,
1282 h
->root
.u
.def
.section
->owner
);
1283 bfd_set_error (bfd_error_bad_value
);
1287 htab
= elf_hash_table (info
);
1289 /* When the symbol is marked with regular reference, if PLT isn't used
1290 or we are building a PIC object, we must keep dynamic relocation
1291 if there is non-GOT reference and use PLT if there is PC-relative
1293 if (need_dynreloc
&& h
->ref_regular
)
1296 for (p
= *head
; p
!= NULL
; p
= p
->next
)
1300 /* Need dynamic relocations for non-GOT reference. */
1304 /* Must use PLT for PC-relative reference. */
1306 need_dynreloc
= bfd_link_pic (info
);
1314 /* Support garbage collection against STT_GNU_IFUNC symbols. */
1315 if (h
->plt
.refcount
<= 0 && h
->got
.refcount
<= 0)
1317 h
->got
= htab
->init_got_offset
;
1318 h
->plt
= htab
->init_plt_offset
;
1323 /* Return and discard space for dynamic relocations against it if
1324 it is never referenced. */
1325 if (!h
->ref_regular
)
1327 if (h
->plt
.refcount
> 0
1328 || h
->got
.refcount
> 0)
1330 h
->got
= htab
->init_got_offset
;
1331 h
->plt
= htab
->init_plt_offset
;
1337 bed
= get_elf_backend_data (info
->output_bfd
);
1338 if (bed
->rela_plts_and_copies_p
)
1339 sizeof_reloc
= bed
->s
->sizeof_rela
;
1341 sizeof_reloc
= bed
->s
->sizeof_rel
;
1343 /* When building a static executable, use iplt, igot.plt and
1344 rela.iplt sections for STT_GNU_IFUNC symbols. */
1345 if (htab
->splt
!= NULL
)
1348 gotplt
= htab
->sgotplt
;
1349 /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */
1350 relplt
= htab
->srelgot
;
1352 /* If this is the first plt entry and PLT is used, make room for
1353 the special first entry. */
1354 if (plt
->size
== 0 && use_plt
)
1355 plt
->size
+= plt_header_size
;
1360 gotplt
= htab
->igotplt
;
1361 relplt
= htab
->irelplt
;
1366 /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
1367 the original value for R_*_IRELATIVE. */
1368 h
->plt
.offset
= plt
->size
;
1370 /* Make room for this entry in the plt/iplt section. */
1371 plt
->size
+= plt_entry_size
;
1373 /* We also need to make an entry in the got.plt/got.iplt section,
1374 which will be placed in the got section by the linker script. */
1375 gotplt
->size
+= got_entry_size
;
1378 /* We also need to make an entry in the rela.plt/.rela.iplt
1379 section for GOTPLT relocation if PLT is used. */
1382 relplt
->size
+= sizeof_reloc
;
1383 relplt
->reloc_count
++;
1386 /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
1387 there is a non-GOT reference in a PIC object or PLT isn't used. */
1388 if (!need_dynreloc
|| !h
->non_got_ref
)
1391 /* Finally, allocate space. */
1395 bfd_size_type count
= 0;
1403 htab
->ifunc_resolvers
= count
!= 0;
1405 /* Dynamic relocations are stored in
1406 1. rela.srelgot section in PIC object.
1407 2. rela.srelgot section in dynamic executable.
1408 3. rela.irelplt section in static executable. */
1409 if (htab
->splt
!= NULL
)
1410 htab
->srelgot
->size
+= count
* sizeof_reloc
;
1413 relplt
->size
+= count
* sizeof_reloc
;
1414 relplt
->reloc_count
+= count
;
1418 /* For STT_GNU_IFUNC symbol, got.plt has the real function address
1419 and got has the PLT entry adddress. We will load the GOT entry
1420 with the PLT entry in finish_dynamic_symbol if it is used. For
1421 branch, it uses got.plt. For symbol value, if PLT is used,
1422 1. Use got.plt in a PIC object if it is forced local or not
1424 2. Use got.plt in a non-PIC object if pointer equality isn't
1426 3. Use got.plt in PIE.
1427 4. Use got.plt if got isn't used.
1428 5. Otherwise use got so that it can be shared among different
1429 objects at run-time.
1430 If PLT isn't used, always use got for symbol value.
1431 We only need to relocate got entry in PIC object or in dynamic
1432 executable without PLT. */
1434 && (h
->got
.refcount
<= 0
1435 || (bfd_link_pic (info
)
1436 && (h
->dynindx
== -1
1437 || h
->forced_local
))
1439 !h
->pointer_equality_needed
)
1440 || htab
->sgot
== NULL
))
1443 h
->got
.offset
= (bfd_vma
) -1;
1449 /* PLT isn't used. */
1450 h
->plt
.offset
= (bfd_vma
) -1;
1452 if (h
->got
.refcount
<= 0)
1454 /* GOT isn't need when there are only relocations for static
1456 h
->got
.offset
= (bfd_vma
) -1;
1460 h
->got
.offset
= htab
->sgot
->size
;
1461 htab
->sgot
->size
+= got_entry_size
;
1462 /* Need to relocate the GOT entry in a PIC object or PLT isn't
1463 used. Otherwise, the GOT entry will be filled with the PLT
1464 entry and dynamic GOT relocation isn't needed. */
1467 /* For non-static executable, dynamic GOT relocation is in
1468 rela.got section, but for static executable, it is
1469 in rela.iplt section. */
1470 if (htab
->splt
!= NULL
)
1471 htab
->srelgot
->size
+= sizeof_reloc
;
1474 relplt
->size
+= sizeof_reloc
;
1475 relplt
->reloc_count
++;
1484 /* Allocate space in .plt, .got and associated reloc sections for
1485 ifunc dynamic relocs. */
1488 elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry
*h
, void *inf
)
1490 struct bfd_link_info
*info
;
1491 /* An example of a bfd_link_hash_indirect symbol is versioned
1492 symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
1493 -> __gxx_personality_v0(bfd_link_hash_defined)
1495 There is no need to process bfd_link_hash_indirect symbols here
1496 because we will also be presented with the concrete instance of
1497 the symbol and loongarch_elf_copy_indirect_symbol () will have been
1498 called to copy all relevant data from the generic to the concrete
1500 if (h
->root
.type
== bfd_link_hash_indirect
)
1503 if (h
->root
.type
== bfd_link_hash_warning
)
1504 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
1506 info
= (struct bfd_link_info
*) inf
;
1508 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
1509 here if it is defined and referenced in a non-shared object. */
1510 if (h
->type
== STT_GNU_IFUNC
&& h
->def_regular
)
1512 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
1513 return local_allocate_ifunc_dyn_relocs (info
, h
,
1520 return _bfd_elf_allocate_ifunc_dyn_relocs (info
, h
,
1531 /* Allocate space in .plt, .got and associated reloc sections for
1532 ifunc dynamic relocs. */
1535 elfNN_allocate_local_ifunc_dynrelocs (void **slot
, void *inf
)
1537 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
1539 if (h
->type
!= STT_GNU_IFUNC
1543 || h
->root
.type
!= bfd_link_hash_defined
)
1546 return elfNN_allocate_ifunc_dynrelocs (h
, inf
);
1549 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
1550 read-only sections. */
1553 maybe_set_textrel (struct elf_link_hash_entry
*h
, void *info_p
)
1557 if (h
->root
.type
== bfd_link_hash_indirect
)
1560 sec
= readonly_dynrelocs (h
);
1563 struct bfd_link_info
*info
= (struct bfd_link_info
*) info_p
;
1565 info
->flags
|= DF_TEXTREL
;
1566 info
->callbacks
->minfo (_("%pB: dynamic relocation against `%pT' in "
1567 "read-only section `%pA'\n"),
1568 sec
->owner
, h
->root
.root
.string
, sec
);
1570 /* Not an error, just cut short the traversal. */
1577 loongarch_elf_size_dynamic_sections (bfd
*output_bfd
,
1578 struct bfd_link_info
*info
)
1580 struct loongarch_elf_link_hash_table
*htab
;
1585 htab
= loongarch_elf_hash_table (info
);
1586 BFD_ASSERT (htab
!= NULL
);
1587 dynobj
= htab
->elf
.dynobj
;
1588 BFD_ASSERT (dynobj
!= NULL
);
1590 if (htab
->elf
.dynamic_sections_created
)
1592 /* Set the contents of the .interp section to the interpreter. */
1593 if (bfd_link_executable (info
) && !info
->nointerp
)
1595 const char *interpreter
;
1596 s
= bfd_get_linker_section (dynobj
, ".interp");
1597 BFD_ASSERT (s
!= NULL
);
1599 if (elf_elfheader (output_bfd
)->e_ident
[EI_CLASS
] == ELFCLASS32
)
1600 interpreter
= "/lib32/ld.so.1";
1601 else if (elf_elfheader (output_bfd
)->e_ident
[EI_CLASS
] == ELFCLASS64
)
1602 interpreter
= "/lib64/ld.so.1";
1604 interpreter
= "/lib/ld.so.1";
1606 s
->contents
= (unsigned char *) interpreter
;
1607 s
->size
= strlen (interpreter
) + 1;
1611 /* Set up .got offsets for local syms, and space for local dynamic
1613 for (ibfd
= info
->input_bfds
; ibfd
!= NULL
; ibfd
= ibfd
->link
.next
)
1615 bfd_signed_vma
*local_got
;
1616 bfd_signed_vma
*end_local_got
;
1617 char *local_tls_type
;
1618 bfd_size_type locsymcount
;
1619 Elf_Internal_Shdr
*symtab_hdr
;
1622 if (!is_loongarch_elf (ibfd
))
1625 for (s
= ibfd
->sections
; s
!= NULL
; s
= s
->next
)
1627 struct elf_dyn_relocs
*p
;
1629 for (p
= elf_section_data (s
)->local_dynrel
; p
!= NULL
; p
= p
->next
)
1631 p
->count
-= p
->pc_count
;
1632 if (!bfd_is_abs_section (p
->sec
)
1633 && bfd_is_abs_section (p
->sec
->output_section
))
1635 /* Input section has been discarded, either because
1636 it is a copy of a linkonce section or due to
1637 linker script /DISCARD/, so we'll be discarding
1640 else if (0 < p
->count
)
1642 srel
= elf_section_data (p
->sec
)->sreloc
;
1643 srel
->size
+= p
->count
* sizeof (ElfNN_External_Rela
);
1644 if ((p
->sec
->output_section
->flags
& SEC_READONLY
) != 0)
1645 info
->flags
|= DF_TEXTREL
;
1650 local_got
= elf_local_got_refcounts (ibfd
);
1654 symtab_hdr
= &elf_symtab_hdr (ibfd
);
1655 locsymcount
= symtab_hdr
->sh_info
;
1656 end_local_got
= local_got
+ locsymcount
;
1657 local_tls_type
= _bfd_loongarch_elf_local_got_tls_type (ibfd
);
1659 srel
= htab
->elf
.srelgot
;
1660 for (; local_got
< end_local_got
; ++local_got
, ++local_tls_type
)
1664 *local_got
= s
->size
;
1666 /* TLS gd use two got. */
1667 if (*local_tls_type
& GOT_TLS_GD
)
1668 s
->size
+= GOT_ENTRY_SIZE
* 2;
1670 /* Normal got, tls ie/ld use one got. */
1671 s
->size
+= GOT_ENTRY_SIZE
;
1673 if (bfd_link_executable (info
)
1674 && (*local_tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
)))
1678 srel
->size
+= sizeof (ElfNN_External_Rela
);
1682 *local_got
= MINUS_ONE
;
1686 /* Allocate global sym .plt and .got entries, and space for global
1687 sym dynamic relocs. */
1688 elf_link_hash_traverse (&htab
->elf
, allocate_dynrelocs
, info
);
1690 /* Allocate global ifunc sym .plt and .got entries, and space for global
1691 ifunc sym dynamic relocs. */
1692 elf_link_hash_traverse (&htab
->elf
, elfNN_allocate_ifunc_dynrelocs
, info
);
1694 /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1695 htab_traverse (htab
->loc_hash_table
,
1696 (void *) elfNN_allocate_local_ifunc_dynrelocs
, info
);
1698 /* Don't allocate .got.plt section if there are no PLT. */
1699 if (htab
->elf
.sgotplt
&& htab
->elf
.sgotplt
->size
== GOTPLT_HEADER_SIZE
1700 && (htab
->elf
.splt
== NULL
|| htab
->elf
.splt
->size
== 0))
1701 htab
->elf
.sgotplt
->size
= 0;
1703 /* The check_relocs and adjust_dynamic_symbol entry points have
1704 determined the sizes of the various dynamic sections. Allocate
1706 for (s
= dynobj
->sections
; s
!= NULL
; s
= s
->next
)
1708 if ((s
->flags
& SEC_LINKER_CREATED
) == 0)
1711 if (s
== htab
->elf
.splt
|| s
== htab
->elf
.iplt
|| s
== htab
->elf
.sgot
1712 || s
== htab
->elf
.sgotplt
|| s
== htab
->elf
.igotplt
1713 || s
== htab
->elf
.sdynbss
|| s
== htab
->elf
.sdynrelro
)
1715 /* Strip this section if we don't need it; see the
1718 else if (strncmp (s
->name
, ".rela", 5) == 0)
1722 /* We use the reloc_count field as a counter if we need
1723 to copy relocs into the output file. */
1729 /* It's not one of our sections. */
1735 /* If we don't need this section, strip it from the
1736 output file. This is mostly to handle .rela.bss and
1737 .rela.plt. We must create both sections in
1738 create_dynamic_sections, because they must be created
1739 before the linker maps input sections to output
1740 sections. The linker does that before
1741 adjust_dynamic_symbol is called, and it is that
1742 function which decides whether anything needs to go
1743 into these sections. */
1744 s
->flags
|= SEC_EXCLUDE
;
1748 if ((s
->flags
& SEC_HAS_CONTENTS
) == 0)
1751 /* Allocate memory for the section contents. Zero the memory
1752 for the benefit of .rela.plt, which has 4 unused entries
1753 at the beginning, and we don't want garbage. */
1754 s
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, s
->size
);
1755 if (s
->contents
== NULL
)
1759 if (elf_hash_table (info
)->dynamic_sections_created
)
1761 /* Add some entries to the .dynamic section. We fill in the
1762 values later, in loongarch_elf_finish_dynamic_sections, but we
1763 must add the entries now so that we get the correct size for
1764 the .dynamic section. The DT_DEBUG entry is filled in by the
1765 dynamic linker and used by the debugger. */
1766 #define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1768 if (bfd_link_executable (info
))
1770 if (!add_dynamic_entry (DT_DEBUG
, 0))
1774 if (htab
->elf
.srelplt
->size
!= 0)
1776 if (!add_dynamic_entry (DT_PLTGOT
, 0)
1777 || !add_dynamic_entry (DT_PLTRELSZ
, 0)
1778 || !add_dynamic_entry (DT_PLTREL
, DT_RELA
)
1779 || !add_dynamic_entry (DT_JMPREL
, 0))
1783 if (!add_dynamic_entry (DT_RELA
, 0)
1784 || !add_dynamic_entry (DT_RELASZ
, 0)
1785 || !add_dynamic_entry (DT_RELAENT
, sizeof (ElfNN_External_Rela
)))
1788 /* If any dynamic relocs apply to a read-only section,
1789 then we need a DT_TEXTREL entry. */
1790 if ((info
->flags
& DF_TEXTREL
) == 0)
1791 elf_link_hash_traverse (&htab
->elf
, maybe_set_textrel
, info
);
1793 if (info
->flags
& DF_TEXTREL
)
1795 if (!add_dynamic_entry (DT_TEXTREL
, 0))
1797 /* Clear the DF_TEXTREL flag. It will be set again if we
1798 write out an actual text relocation; we may not, because
1799 at this point we do not know whether e.g. any .eh_frame
1800 absolute relocations have been converted to PC-relative. */
1801 info
->flags
&= ~DF_TEXTREL
;
1804 #undef add_dynamic_entry
1809 #define LARCH_LD_STACK_DEPTH 16
1810 static int64_t larch_opc_stack
[LARCH_LD_STACK_DEPTH
];
1811 static size_t larch_stack_top
= 0;
1813 static bfd_reloc_status_type
1814 loongarch_push (int64_t val
)
1816 if (LARCH_LD_STACK_DEPTH
<= larch_stack_top
)
1817 return bfd_reloc_outofrange
;
1818 larch_opc_stack
[larch_stack_top
++] = val
;
1819 return bfd_reloc_ok
;
1822 static bfd_reloc_status_type
1823 loongarch_pop (int64_t *val
)
1825 if (larch_stack_top
== 0)
1826 return bfd_reloc_outofrange
;
1828 *val
= larch_opc_stack
[--larch_stack_top
];
1829 return bfd_reloc_ok
;
1832 static bfd_reloc_status_type
1833 loongarch_top (int64_t *val
)
1835 if (larch_stack_top
== 0)
1836 return bfd_reloc_outofrange
;
1838 *val
= larch_opc_stack
[larch_stack_top
- 1];
1839 return bfd_reloc_ok
;
1843 loongarch_elf_append_rela (bfd
*abfd
, asection
*s
, Elf_Internal_Rela
*rel
)
1845 BFD_ASSERT (s
&& s
->contents
);
1846 const struct elf_backend_data
*bed
;
1849 bed
= get_elf_backend_data (abfd
);
1850 if (!(s
->size
> s
->reloc_count
* bed
->s
->sizeof_rela
))
1851 BFD_ASSERT (s
->size
> s
->reloc_count
* bed
->s
->sizeof_rela
);
1852 loc
= s
->contents
+ (s
->reloc_count
++ * bed
->s
->sizeof_rela
);
1853 bed
->s
->swap_reloca_out (abfd
, rel
, loc
);
1856 /* Check rel->r_offset in range of contents. */
1857 static bfd_reloc_status_type
1858 loongarch_check_offset (const Elf_Internal_Rela
*rel
,
1859 const asection
*input_section
)
1861 if (0 == strcmp(input_section
->name
, ".text")
1862 && rel
->r_offset
> input_section
->size
)
1863 return bfd_reloc_overflow
;
1865 return bfd_reloc_ok
;
1868 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1870 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1871 if (ret == bfd_reloc_ok) \
1873 ret = loongarch_pop (&op1); \
1874 if (ret == bfd_reloc_ok) \
1875 ret = loongarch_push (op3); \
1880 static bfd_reloc_status_type
1881 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela
*rel
,
1882 const asection
*input_section ATTRIBUTE_UNUSED
,
1883 reloc_howto_type
*howto
, bfd
*input_bfd
,
1884 bfd_byte
*contents
, bfd_vma reloc_val
)
1886 int bits
= bfd_get_reloc_size (howto
) * 8;
1887 uint32_t insn
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
1889 if (!loongarch_adjust_reloc_bitsfield(howto
, &reloc_val
))
1890 return bfd_reloc_overflow
;
1892 insn
= (insn
& (uint32_t)howto
->src_mask
)
1893 | ((insn
& (~(uint32_t)howto
->dst_mask
)) | reloc_val
);
1895 bfd_put (bits
, input_bfd
, insn
, contents
+ rel
->r_offset
);
1897 return bfd_reloc_ok
;
1900 static bfd_reloc_status_type
1901 perform_relocation (const Elf_Internal_Rela
*rel
, asection
*input_section
,
1902 reloc_howto_type
*howto
, bfd_vma value
,
1903 bfd
*input_bfd
, bfd_byte
*contents
)
1905 int64_t opr1
, opr2
, opr3
;
1906 bfd_reloc_status_type r
= bfd_reloc_ok
;
1907 int bits
= bfd_get_reloc_size (howto
) * 8;
1909 switch (ELFNN_R_TYPE (rel
->r_info
))
1911 case R_LARCH_SOP_PUSH_PCREL
:
1912 case R_LARCH_SOP_PUSH_ABSOLUTE
:
1913 case R_LARCH_SOP_PUSH_GPREL
:
1914 case R_LARCH_SOP_PUSH_TLS_TPREL
:
1915 case R_LARCH_SOP_PUSH_TLS_GOT
:
1916 case R_LARCH_SOP_PUSH_TLS_GD
:
1917 case R_LARCH_SOP_PUSH_PLT_PCREL
:
1918 r
= loongarch_push (value
);
1921 case R_LARCH_SOP_PUSH_DUP
:
1922 r
= loongarch_pop (&opr1
);
1923 if (r
== bfd_reloc_ok
)
1925 r
= loongarch_push (opr1
);
1926 if (r
== bfd_reloc_ok
)
1927 r
= loongarch_push (opr1
);
1931 case R_LARCH_SOP_ASSERT
:
1932 r
= loongarch_pop (&opr1
);
1933 if (r
!= bfd_reloc_ok
|| !opr1
)
1934 r
= bfd_reloc_notsupported
;
1937 case R_LARCH_SOP_NOT
:
1938 r
= loongarch_pop (&opr1
);
1939 if (r
== bfd_reloc_ok
)
1940 r
= loongarch_push (!opr1
);
1943 case R_LARCH_SOP_SUB
:
1944 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
- opr2
);
1947 case R_LARCH_SOP_SL
:
1948 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
<< opr2
);
1951 case R_LARCH_SOP_SR
:
1952 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
>> opr2
);
1955 case R_LARCH_SOP_AND
:
1956 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
& opr2
);
1959 case R_LARCH_SOP_ADD
:
1960 r
= LARCH_RELOC_PERFORM_3OP (opr1
, opr2
, opr1
+ opr2
);
1963 case R_LARCH_SOP_IF_ELSE
:
1964 r
= loongarch_pop (&opr3
);
1965 if (r
== bfd_reloc_ok
)
1967 r
= loongarch_pop (&opr2
);
1968 if (r
== bfd_reloc_ok
)
1970 r
= loongarch_pop (&opr1
);
1971 if (r
== bfd_reloc_ok
)
1972 r
= loongarch_push (opr1
? opr2
: opr3
);
1977 case R_LARCH_SOP_POP_32_S_10_5
:
1978 case R_LARCH_SOP_POP_32_S_10_12
:
1979 case R_LARCH_SOP_POP_32_S_10_16
:
1980 case R_LARCH_SOP_POP_32_S_10_16_S2
:
1981 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2
:
1982 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2
:
1983 case R_LARCH_SOP_POP_32_S_5_20
:
1984 case R_LARCH_SOP_POP_32_U_10_12
:
1985 case R_LARCH_SOP_POP_32_U
:
1986 r
= loongarch_pop (&opr1
);
1987 if (r
!= bfd_reloc_ok
)
1989 r
= loongarch_check_offset (rel
, input_section
);
1990 if (r
!= bfd_reloc_ok
)
1993 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
1995 contents
, (bfd_vma
)opr1
);
1998 case R_LARCH_TLS_DTPREL32
:
2000 case R_LARCH_TLS_DTPREL64
:
2002 r
= loongarch_check_offset (rel
, input_section
);
2003 if (r
!= bfd_reloc_ok
)
2006 bfd_put (bits
, input_bfd
, value
, contents
+ rel
->r_offset
);
2014 r
= loongarch_check_offset (rel
, input_section
);
2015 if (r
!= bfd_reloc_ok
)
2018 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
2019 bfd_put (bits
, input_bfd
, opr1
+ value
, contents
+ rel
->r_offset
);
2027 r
= loongarch_check_offset (rel
, input_section
);
2028 if (r
!= bfd_reloc_ok
)
2031 opr1
= bfd_get (bits
, input_bfd
, contents
+ rel
->r_offset
);
2032 bfd_put (bits
, input_bfd
, opr1
- value
, contents
+ rel
->r_offset
);
2035 /* For eh_frame and debug info. */
2036 case R_LARCH_32_PCREL
:
2037 value
-= sec_addr (input_section
) + rel
->r_offset
;
2038 value
+= rel
->r_addend
;
2039 bfd_vma word
= bfd_get (howto
->bitsize
, input_bfd
,
2040 contents
+ rel
->r_offset
);
2041 word
= (word
& ~howto
->dst_mask
) | (value
& howto
->dst_mask
);
2042 bfd_put (howto
->bitsize
, input_bfd
, word
, contents
+ rel
->r_offset
);
2047 R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */
2051 case R_LARCH_ABS_HI20
:
2052 case R_LARCH_ABS_LO12
:
2053 case R_LARCH_ABS64_LO20
:
2054 case R_LARCH_ABS64_HI12
:
2055 case R_LARCH_PCALA_HI20
:
2056 case R_LARCH_PCALA_LO12
:
2057 case R_LARCH_PCALA64_LO20
:
2058 case R_LARCH_PCALA64_HI12
:
2059 case R_LARCH_GOT_PC_HI20
:
2060 case R_LARCH_GOT_PC_LO12
:
2061 case R_LARCH_GOT64_PC_LO20
:
2062 case R_LARCH_GOT64_PC_HI12
:
2063 case R_LARCH_GOT_HI20
:
2064 case R_LARCH_GOT_LO12
:
2065 case R_LARCH_GOT64_LO20
:
2066 case R_LARCH_GOT64_HI12
:
2067 case R_LARCH_TLS_LE_HI20
:
2068 case R_LARCH_TLS_LE_LO12
:
2069 case R_LARCH_TLS_LE64_LO20
:
2070 case R_LARCH_TLS_LE64_HI12
:
2071 case R_LARCH_TLS_IE_PC_HI20
:
2072 case R_LARCH_TLS_IE_PC_LO12
:
2073 case R_LARCH_TLS_IE64_PC_LO20
:
2074 case R_LARCH_TLS_IE64_PC_HI12
:
2075 case R_LARCH_TLS_IE_HI20
:
2076 case R_LARCH_TLS_IE_LO12
:
2077 case R_LARCH_TLS_IE64_LO20
:
2078 case R_LARCH_TLS_IE64_HI12
:
2079 case R_LARCH_TLS_LD_PC_HI20
:
2080 case R_LARCH_TLS_LD_HI20
:
2081 case R_LARCH_TLS_GD_PC_HI20
:
2082 case R_LARCH_TLS_GD_HI20
:
2083 r
= loongarch_check_offset (rel
, input_section
);
2084 if (r
!= bfd_reloc_ok
)
2087 r
= loongarch_reloc_rewrite_imm_insn (rel
, input_section
,
2096 r
= bfd_reloc_notsupported
;
2101 #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
2109 Elf_Internal_Sym
*sym
;
2110 struct elf_link_hash_entry
*h
;
2113 } larch_reloc_queue
[LARCH_RECENT_RELOC_QUEUE_LENGTH
];
2114 static size_t larch_reloc_queue_head
= 0;
2115 static size_t larch_reloc_queue_tail
= 0;
2118 loongarch_sym_name (bfd
*input_bfd
, struct elf_link_hash_entry
*h
,
2119 Elf_Internal_Sym
*sym
)
2121 const char *ret
= NULL
;
2123 ret
= bfd_elf_string_from_elf_section (input_bfd
,
2124 elf_symtab_hdr (input_bfd
).sh_link
,
2127 ret
= h
->root
.root
.string
;
2129 if (ret
== NULL
|| *ret
== '\0')
2135 loongarch_record_one_reloc (bfd
*abfd
, asection
*section
, int r_type
,
2136 bfd_vma r_offset
, Elf_Internal_Sym
*sym
,
2137 struct elf_link_hash_entry
*h
, bfd_vma addend
)
2139 if ((larch_reloc_queue_head
== 0
2140 && larch_reloc_queue_tail
== LARCH_RECENT_RELOC_QUEUE_LENGTH
- 1)
2141 || larch_reloc_queue_head
== larch_reloc_queue_tail
+ 1)
2142 larch_reloc_queue_head
=
2143 (larch_reloc_queue_head
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
2144 larch_reloc_queue
[larch_reloc_queue_tail
].bfd
= abfd
;
2145 larch_reloc_queue
[larch_reloc_queue_tail
].section
= section
;
2146 larch_reloc_queue
[larch_reloc_queue_tail
].r_offset
= r_offset
;
2147 larch_reloc_queue
[larch_reloc_queue_tail
].r_type
= r_type
;
2148 larch_reloc_queue
[larch_reloc_queue_tail
].sym
= sym
;
2149 larch_reloc_queue
[larch_reloc_queue_tail
].h
= h
;
2150 larch_reloc_queue
[larch_reloc_queue_tail
].addend
= addend
;
2151 loongarch_top (&larch_reloc_queue
[larch_reloc_queue_tail
].top_then
);
2152 larch_reloc_queue_tail
=
2153 (larch_reloc_queue_tail
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
2157 loongarch_dump_reloc_record (void (*p
) (const char *fmt
, ...))
2159 size_t i
= larch_reloc_queue_head
;
2161 asection
*section
= NULL
;
2162 bfd_vma r_offset
= 0;
2164 p ("Dump relocate record:\n");
2165 p ("stack top\t\trelocation name\t\tsymbol");
2166 while (i
!= larch_reloc_queue_tail
)
2168 if (a_bfd
!= larch_reloc_queue
[i
].bfd
2169 || section
!= larch_reloc_queue
[i
].section
2170 || r_offset
!= larch_reloc_queue
[i
].r_offset
)
2172 a_bfd
= larch_reloc_queue
[i
].bfd
;
2173 section
= larch_reloc_queue
[i
].section
;
2174 r_offset
= larch_reloc_queue
[i
].r_offset
;
2175 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue
[i
].bfd
,
2176 larch_reloc_queue
[i
].section
, larch_reloc_queue
[i
].r_offset
);
2180 inited
= 1, p ("...\n");
2182 reloc_howto_type
*howto
=
2183 loongarch_elf_rtype_to_howto (larch_reloc_queue
[i
].bfd
,
2184 larch_reloc_queue
[i
].r_type
);
2185 p ("0x%V %s\t`%s'", (bfd_vma
) larch_reloc_queue
[i
].top_then
,
2186 howto
? howto
->name
: "<unknown reloc>",
2187 loongarch_sym_name (larch_reloc_queue
[i
].bfd
, larch_reloc_queue
[i
].h
,
2188 larch_reloc_queue
[i
].sym
));
2190 long addend
= larch_reloc_queue
[i
].addend
;
2192 p (" - %ld", -addend
);
2193 else if (0 < addend
)
2194 p (" + %ld(0x%v)", addend
, larch_reloc_queue
[i
].addend
);
2197 i
= (i
+ 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH
;
2200 "-- Record dump end --\n\n");
2204 loongarch_reloc_is_fatal (struct bfd_link_info
*info
,
2206 asection
*input_section
,
2207 Elf_Internal_Rela
*rel
,
2208 reloc_howto_type
*howto
,
2209 bfd_reloc_status_type rtype
,
2217 /* 'dangerous' means we do it but can't promise it's ok
2218 'unsupport' means out of ability of relocation type
2219 'undefined' means we can't deal with the undefined symbol. */
2220 case bfd_reloc_undefined
:
2221 info
->callbacks
->undefined_symbol (info
, name
, input_bfd
, input_section
,
2222 rel
->r_offset
, true);
2223 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2224 input_bfd
, input_section
, rel
->r_offset
,
2226 is_undefweak
? "[undefweak] " : "", name
, msg
);
2228 case bfd_reloc_dangerous
:
2229 info
->callbacks
->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
2230 input_bfd
, input_section
, rel
->r_offset
,
2232 is_undefweak
? "[undefweak] " : "", name
, msg
);
2235 case bfd_reloc_notsupported
:
2236 info
->callbacks
->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2237 input_bfd
, input_section
, rel
->r_offset
,
2239 is_undefweak
? "[undefweak] " : "", name
, msg
);
2247 #define RELOCATE_CALC_PC32_HI20(relocation, pc) \
2249 bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2250 pc = pc & (~(bfd_vma)0xfff); \
2253 relocation += 0x1000; \
2255 relocation &= ~(bfd_vma)0xfff; \
2259 #define RELOCATE_CALC_PC64_HI32(relocation, pc) \
2261 bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2264 relocation -= 0x100000000; \
2266 relocation -= (pc & ~(bfd_vma)0xffffffff); \
2270 loongarch_elf_relocate_section (bfd
*output_bfd
, struct bfd_link_info
*info
,
2271 bfd
*input_bfd
, asection
*input_section
,
2272 bfd_byte
*contents
, Elf_Internal_Rela
*relocs
,
2273 Elf_Internal_Sym
*local_syms
,
2274 asection
**local_sections
)
2276 Elf_Internal_Rela
*rel
;
2277 Elf_Internal_Rela
*relend
;
2279 asection
*sreloc
= elf_section_data (input_section
)->sreloc
;
2280 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
2281 Elf_Internal_Shdr
*symtab_hdr
= &elf_symtab_hdr (input_bfd
);
2282 struct elf_link_hash_entry
**sym_hashes
= elf_sym_hashes (input_bfd
);
2283 bfd_vma
*local_got_offsets
= elf_local_got_offsets (input_bfd
);
2284 bool is_pic
= bfd_link_pic (info
);
2285 bool is_dyn
= elf_hash_table (info
)->dynamic_sections_created
;
2286 asection
*plt
= htab
->elf
.splt
? htab
->elf
.splt
: htab
->elf
.iplt
;
2287 asection
*got
= htab
->elf
.sgot
;
2289 relend
= relocs
+ input_section
->reloc_count
;
2290 for (rel
= relocs
; rel
< relend
; rel
++)
2292 int r_type
= ELFNN_R_TYPE (rel
->r_info
);
2293 unsigned long r_symndx
= ELFNN_R_SYM (rel
->r_info
);
2294 bfd_vma pc
= sec_addr (input_section
) + rel
->r_offset
;
2295 reloc_howto_type
*howto
= NULL
;
2296 asection
*sec
= NULL
;
2297 Elf_Internal_Sym
*sym
= NULL
;
2298 struct elf_link_hash_entry
*h
= NULL
;
2300 bfd_reloc_status_type r
= bfd_reloc_ok
;
2301 bool is_ie
, is_undefweak
, unresolved_reloc
, defined_local
;
2302 bool resolved_local
, resolved_dynly
, resolved_to_const
;
2304 bfd_vma relocation
, off
, ie_off
;
2307 howto
= loongarch_elf_rtype_to_howto (input_bfd
, r_type
);
2308 if (howto
== NULL
|| r_type
== R_LARCH_GNU_VTINHERIT
2309 || r_type
== R_LARCH_GNU_VTENTRY
)
2312 /* This is a final link. */
2313 if (r_symndx
< symtab_hdr
->sh_info
)
2315 is_undefweak
= false;
2316 unresolved_reloc
= false;
2317 sym
= local_syms
+ r_symndx
;
2318 sec
= local_sections
[r_symndx
];
2319 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
2321 /* Relocate against local STT_GNU_IFUNC symbol. */
2322 if (!bfd_link_relocatable (info
)
2323 && ELF_ST_TYPE (sym
->st_info
) == STT_GNU_IFUNC
)
2325 h
= elfNN_loongarch_get_local_sym_hash (htab
, input_bfd
, rel
,
2330 /* Set STT_GNU_IFUNC symbol value. */
2331 h
->root
.u
.def
.value
= sym
->st_value
;
2332 h
->root
.u
.def
.section
= sec
;
2334 defined_local
= true;
2335 resolved_local
= true;
2336 resolved_dynly
= false;
2337 resolved_to_const
= false;
2339 /* Calc in funtion elf_link_input_bfd,
2340 * if #define elf_backend_rela_normal to 1. */
2341 if (bfd_link_relocatable (info
)
2342 && ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
2347 bool warned
, ignored
;
2349 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
2350 r_symndx
, symtab_hdr
, sym_hashes
,
2352 unresolved_reloc
, warned
, ignored
);
2353 /* Here means symbol isn't local symbol only and 'h != NULL'. */
2355 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
2356 symbol. And 'dynamic_undefined_weak' specify what to do when
2357 meeting undefweak. */
2359 if ((is_undefweak
= h
->root
.type
== bfd_link_hash_undefweak
))
2361 defined_local
= false;
2362 resolved_local
= false;
2363 resolved_to_const
= (!is_dyn
|| h
->dynindx
== -1
2364 || UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
));
2365 resolved_dynly
= !resolved_local
&& !resolved_to_const
;
2369 /* Symbol undefined offen means failed already. I don't know why
2370 'warned' here but I guess it want to continue relocating as if
2371 no error occures to find other errors as more as possible. */
2373 /* To avoid generating warning messages about truncated
2374 relocations, set the relocation's address to be the same as
2375 the start of this section. */
2376 relocation
= (input_section
->output_section
2377 ? input_section
->output_section
->vma
2380 defined_local
= relocation
!= 0;
2381 resolved_local
= defined_local
;
2382 resolved_to_const
= !resolved_local
;
2383 resolved_dynly
= false;
2387 defined_local
= !unresolved_reloc
&& !ignored
;
2389 defined_local
&& SYMBOL_REFERENCES_LOCAL (info
, h
);
2390 resolved_dynly
= !resolved_local
;
2391 resolved_to_const
= !resolved_local
&& !resolved_dynly
;
2395 name
= loongarch_sym_name (input_bfd
, h
, sym
);
2397 if (sec
!= NULL
&& discarded_section (sec
))
2398 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
, rel
,
2399 1, relend
, howto
, 0, contents
);
2401 if (bfd_link_relocatable (info
))
2404 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2405 from removed linkonce sections, or sections discarded by a linker
2406 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2407 if (r_symndx
== STN_UNDEF
|| bfd_is_abs_section (sec
))
2409 defined_local
= false;
2410 resolved_local
= false;
2411 resolved_dynly
= false;
2412 resolved_to_const
= true;
2415 /* The ifunc reference generate plt. */
2416 if (h
&& h
->type
== STT_GNU_IFUNC
&& h
->plt
.offset
!= MINUS_ONE
)
2418 defined_local
= true;
2419 resolved_local
= true;
2420 resolved_dynly
= false;
2421 resolved_to_const
= false;
2422 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2425 unresolved_reloc
= resolved_dynly
;
2427 BFD_ASSERT (resolved_local
+ resolved_dynly
+ resolved_to_const
== 1);
2429 /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));. */
2431 BFD_ASSERT (!resolved_local
|| defined_local
);
2436 case R_LARCH_MARK_PCREL
:
2437 case R_LARCH_MARK_LA
:
2439 r
= bfd_reloc_continue
;
2440 unresolved_reloc
= false;
2445 if (resolved_dynly
|| (is_pic
&& resolved_local
))
2447 Elf_Internal_Rela outrel
;
2449 /* When generating a shared object, these relocations are copied
2450 into the output file to be resolved at run time. */
2452 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2456 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2457 && (input_section
->flags
& SEC_ALLOC
));
2459 outrel
.r_offset
+= sec_addr (input_section
);
2461 /* A pointer point to a ifunc symbol. */
2462 if (h
&& h
->type
== STT_GNU_IFUNC
)
2464 if (h
->dynindx
== -1)
2466 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
2467 outrel
.r_addend
= (h
->root
.u
.def
.value
2468 + h
->root
.u
.def
.section
->output_section
->vma
2469 + h
->root
.u
.def
.section
->output_offset
);
2473 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
2474 outrel
.r_addend
= 0;
2477 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2480 if (htab
->elf
.splt
!= NULL
)
2481 sreloc
= htab
->elf
.srelgot
;
2483 sreloc
= htab
->elf
.irelplt
;
2488 if (bfd_link_pic (info
))
2489 sreloc
= htab
->elf
.irelifunc
;
2490 else if (htab
->elf
.splt
!= NULL
)
2491 sreloc
= htab
->elf
.srelgot
;
2493 sreloc
= htab
->elf
.irelplt
;
2496 else if (resolved_dynly
)
2498 if (h
->dynindx
== -1)
2500 if (h
->root
.type
== bfd_link_hash_undefined
)
2501 (*info
->callbacks
->undefined_symbol
)
2502 (info
, name
, input_bfd
, input_section
,
2503 rel
->r_offset
, true);
2505 outrel
.r_info
= ELFNN_R_INFO (0, r_type
);
2508 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2510 outrel
.r_addend
= rel
->r_addend
;
2514 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2515 outrel
.r_addend
= relocation
+ rel
->r_addend
;
2518 /* No alloc space of func allocate_dynrelocs. */
2519 if (unresolved_reloc
2520 && !(h
&& (h
->is_weakalias
|| !h
->dyn_relocs
)))
2521 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2524 relocation
+= rel
->r_addend
;
2538 fatal
= (loongarch_reloc_is_fatal
2539 (info
, input_bfd
, input_section
, rel
, howto
,
2540 bfd_reloc_undefined
, is_undefweak
, name
,
2541 "Can't be resolved dynamically. "
2542 "If this procedure is hand-written assembly,\n"
2543 "there must be something like '.dword sym1 - sym2' "
2544 "to generate these relocs\n"
2545 "and we can't get known link-time address of "
2548 relocation
+= rel
->r_addend
;
2551 case R_LARCH_TLS_DTPREL32
:
2552 case R_LARCH_TLS_DTPREL64
:
2555 Elf_Internal_Rela outrel
;
2557 outrel
.r_offset
= _bfd_elf_section_offset (output_bfd
, info
,
2560 unresolved_reloc
= (!((bfd_vma
) -2 <= outrel
.r_offset
)
2561 && (input_section
->flags
& SEC_ALLOC
));
2562 outrel
.r_info
= ELFNN_R_INFO (h
->dynindx
, r_type
);
2563 outrel
.r_offset
+= sec_addr (input_section
);
2564 outrel
.r_addend
= rel
->r_addend
;
2565 if (unresolved_reloc
)
2566 loongarch_elf_append_rela (output_bfd
, sreloc
, &outrel
);
2570 if (resolved_to_const
)
2571 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
, input_section
,
2573 bfd_reloc_notsupported
,
2578 if (!elf_hash_table (info
)->tls_sec
)
2580 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
,
2581 input_section
, rel
, howto
, bfd_reloc_notsupported
,
2582 is_undefweak
, name
, "TLS section not be created");
2585 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
2589 fatal
= loongarch_reloc_is_fatal (info
, input_bfd
,
2590 input_section
, rel
, howto
, bfd_reloc_undefined
,
2592 "TLS LE just can be resolved local only.");
2597 case R_LARCH_SOP_PUSH_TLS_TPREL
:
2600 if (!elf_hash_table (info
)->tls_sec
)
2601 fatal
= (loongarch_reloc_is_fatal
2602 (info
, input_bfd
, input_section
, rel
, howto
,
2603 bfd_reloc_notsupported
, is_undefweak
, name
,
2604 "TLS section not be created"));
2606 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
2609 fatal
= (loongarch_reloc_is_fatal
2610 (info
, input_bfd
, input_section
, rel
, howto
,
2611 bfd_reloc_undefined
, is_undefweak
, name
,
2612 "TLS LE just can be resolved local only."));
2615 case R_LARCH_SOP_PUSH_ABSOLUTE
:
2619 fatal
= (loongarch_reloc_is_fatal
2620 (info
, input_bfd
, input_section
, rel
, howto
,
2621 bfd_reloc_dangerous
, is_undefweak
, name
,
2622 "Someone require us to resolve undefweak "
2623 "symbol dynamically. \n"
2624 "But this reloc can't be done. "
2625 "I think I can't throw error "
2627 "so I resolved it to 0. "
2628 "I suggest to re-compile with '-fpic'."));
2631 unresolved_reloc
= false;
2635 if (resolved_to_const
)
2637 relocation
+= rel
->r_addend
;
2643 fatal
= (loongarch_reloc_is_fatal
2644 (info
, input_bfd
, input_section
, rel
, howto
,
2645 bfd_reloc_notsupported
, is_undefweak
, name
,
2646 "Under PIC we don't know load address. Re-compile "
2653 if (!(plt
&& h
&& h
->plt
.offset
!= MINUS_ONE
))
2655 fatal
= (loongarch_reloc_is_fatal
2656 (info
, input_bfd
, input_section
, rel
, howto
,
2657 bfd_reloc_undefined
, is_undefweak
, name
,
2658 "Can't be resolved dynamically. Try to re-compile "
2663 if (rel
->r_addend
!= 0)
2665 fatal
= (loongarch_reloc_is_fatal
2666 (info
, input_bfd
, input_section
, rel
, howto
,
2667 bfd_reloc_notsupported
, is_undefweak
, name
,
2668 "Shouldn't be with r_addend."));
2672 relocation
= sec_addr (plt
) + h
->plt
.offset
;
2673 unresolved_reloc
= false;
2679 relocation
+= rel
->r_addend
;
2685 case R_LARCH_SOP_PUSH_PCREL
:
2686 case R_LARCH_SOP_PUSH_PLT_PCREL
:
2687 unresolved_reloc
= false;
2695 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
2698 fatal
= (loongarch_reloc_is_fatal
2699 (info
, input_bfd
, input_section
, rel
, howto
,
2700 bfd_reloc_dangerous
, is_undefweak
, name
,
2701 "Undefweak need to be resolved dynamically, "
2702 "but PLT stub doesn't represent."));
2707 if (!(defined_local
|| (h
&& h
->plt
.offset
!= MINUS_ONE
)))
2709 fatal
= (loongarch_reloc_is_fatal
2710 (info
, input_bfd
, input_section
, rel
, howto
,
2711 bfd_reloc_undefined
, is_undefweak
, name
,
2712 "PLT stub does not represent and "
2713 "symbol not defined."));
2719 else /* if (resolved_dynly) */
2721 if (!(h
&& h
->plt
.offset
!= MINUS_ONE
))
2722 fatal
= (loongarch_reloc_is_fatal
2723 (info
, input_bfd
, input_section
, rel
, howto
,
2724 bfd_reloc_dangerous
, is_undefweak
, name
,
2725 "Internal: PLT stub doesn't represent. "
2726 "Resolve it with pcrel"));
2733 if ((i
& 1) == 0 && defined_local
)
2736 relocation
+= rel
->r_addend
;
2740 if ((i
& 1) && h
&& h
->plt
.offset
!= MINUS_ONE
)
2742 if (rel
->r_addend
!= 0)
2744 fatal
= (loongarch_reloc_is_fatal
2745 (info
, input_bfd
, input_section
, rel
, howto
,
2746 bfd_reloc_notsupported
, is_undefweak
, name
,
2747 "PLT shouldn't be with r_addend."));
2750 relocation
= sec_addr (plt
) + h
->plt
.offset
- pc
;
2756 case R_LARCH_SOP_PUSH_GPREL
:
2757 unresolved_reloc
= false;
2759 if (rel
->r_addend
!= 0)
2761 fatal
= (loongarch_reloc_is_fatal
2762 (info
, input_bfd
, input_section
, rel
, howto
,
2763 bfd_reloc_notsupported
, is_undefweak
, name
,
2764 "Shouldn't be with r_addend."));
2770 off
= h
->got
.offset
& (~1);
2772 if (h
->got
.offset
== MINUS_ONE
&& h
->type
!= STT_GNU_IFUNC
)
2774 fatal
= (loongarch_reloc_is_fatal
2775 (info
, input_bfd
, input_section
, rel
, howto
,
2776 bfd_reloc_notsupported
, is_undefweak
, name
,
2777 "Internal: GOT entry doesn't represent."));
2781 /* Hidden symbol not has .got entry, only .got.plt entry
2782 so gprel is (plt - got). */
2783 if (h
->got
.offset
== MINUS_ONE
&& h
->type
== STT_GNU_IFUNC
)
2785 if (h
->plt
.offset
== (bfd_vma
) -1)
2790 bfd_vma plt_index
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
2791 off
= plt_index
* GOT_ENTRY_SIZE
;
2793 if (htab
->elf
.splt
!= NULL
)
2795 /* Section .plt header is 2 times of plt entry. */
2796 off
= sec_addr (htab
->elf
.sgotplt
) + off
2797 - sec_addr (htab
->elf
.sgot
);
2801 /* Section iplt not has plt header. */
2802 off
= sec_addr (htab
->elf
.igotplt
) + off
2803 - sec_addr (htab
->elf
.sgot
);
2807 if ((h
->got
.offset
& 1) == 0)
2809 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn
,
2810 bfd_link_pic (info
), h
)
2811 && ((bfd_link_pic (info
)
2812 && SYMBOL_REFERENCES_LOCAL (info
, h
))))
2814 /* This is actually a static link, or it is a
2815 -Bsymbolic link and the symbol is defined
2816 locally, or the symbol was forced to be local
2817 because of a version file. We must initialize
2818 this entry in the global offset table. Since the
2819 offset must always be a multiple of the word size,
2820 we use the least significant bit to record whether
2821 we have initialized it already.
2823 When doing a dynamic link, we create a rela.got
2824 relocation entry to initialize the value. This
2825 is done in the finish_dynamic_symbol routine. */
2829 fatal
= (loongarch_reloc_is_fatal
2830 (info
, input_bfd
, input_section
, rel
, howto
,
2831 bfd_reloc_dangerous
, is_undefweak
, name
,
2832 "Internal: here shouldn't dynamic."));
2835 if (!(defined_local
|| resolved_to_const
))
2837 fatal
= (loongarch_reloc_is_fatal
2838 (info
, input_bfd
, input_section
, rel
, howto
,
2839 bfd_reloc_undefined
, is_undefweak
, name
,
2845 Elf_Internal_Rela outrel
;
2846 /* We need to generate a R_LARCH_RELATIVE reloc
2847 for the dynamic linker. */
2848 s
= htab
->elf
.srelgot
;
2851 fatal
= loongarch_reloc_is_fatal
2853 input_section
, rel
, howto
,
2854 bfd_reloc_notsupported
, is_undefweak
, name
,
2855 "Internal: '.rel.got' not represent");
2859 outrel
.r_offset
= sec_addr (got
) + off
;
2860 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2861 outrel
.r_addend
= relocation
; /* Link-time addr. */
2862 loongarch_elf_append_rela (output_bfd
, s
, &outrel
);
2864 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2870 if (!local_got_offsets
)
2872 fatal
= (loongarch_reloc_is_fatal
2873 (info
, input_bfd
, input_section
, rel
, howto
,
2874 bfd_reloc_notsupported
, is_undefweak
, name
,
2875 "Internal: local got offsets not reporesent."));
2879 off
= local_got_offsets
[r_symndx
] & (~1);
2881 if (local_got_offsets
[r_symndx
] == MINUS_ONE
)
2883 fatal
= (loongarch_reloc_is_fatal
2884 (info
, input_bfd
, input_section
, rel
, howto
,
2885 bfd_reloc_notsupported
, is_undefweak
, name
,
2886 "Internal: GOT entry doesn't represent."));
2890 /* The offset must always be a multiple of the word size.
2891 So, we can use the least significant bit to record
2892 whether we have already processed this entry. */
2893 if ((local_got_offsets
[r_symndx
] & 1) == 0)
2898 Elf_Internal_Rela outrel
;
2899 /* We need to generate a R_LARCH_RELATIVE reloc
2900 for the dynamic linker. */
2901 s
= htab
->elf
.srelgot
;
2904 fatal
= (loongarch_reloc_is_fatal
2905 (info
, input_bfd
, input_section
, rel
, howto
,
2906 bfd_reloc_notsupported
, is_undefweak
, name
,
2907 "Internal: '.rel.got' not represent"));
2911 outrel
.r_offset
= sec_addr (got
) + off
;
2912 outrel
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
2913 outrel
.r_addend
= relocation
; /* Link-time addr. */
2914 loongarch_elf_append_rela (output_bfd
, s
, &outrel
);
2917 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ off
);
2918 local_got_offsets
[r_symndx
] |= 1;
2925 case R_LARCH_SOP_PUSH_TLS_GOT
:
2926 case R_LARCH_SOP_PUSH_TLS_GD
:
2928 unresolved_reloc
= false;
2929 if (r_type
== R_LARCH_SOP_PUSH_TLS_GOT
)
2932 bfd_vma got_off
= 0;
2935 got_off
= h
->got
.offset
;
2940 got_off
= local_got_offsets
[r_symndx
];
2941 local_got_offsets
[r_symndx
] |= 1;
2944 BFD_ASSERT (got_off
!= MINUS_ONE
);
2947 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
2948 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
2949 ie_off
= 2 * GOT_ENTRY_SIZE
;
2951 if ((got_off
& 1) == 0)
2953 Elf_Internal_Rela rela
;
2954 asection
*srel
= htab
->elf
.srelgot
;
2955 bfd_vma tls_block_off
= 0;
2957 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2959 BFD_ASSERT (elf_hash_table (info
)->tls_sec
);
2960 tls_block_off
= relocation
2961 - elf_hash_table (info
)->tls_sec
->vma
;
2964 if (tls_type
& GOT_TLS_GD
)
2966 rela
.r_offset
= sec_addr (got
) + got_off
;
2968 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
2970 /* Local sym, used in exec, set module id 1. */
2971 if (bfd_link_executable (info
))
2972 bfd_put_NN (output_bfd
, 1, got
->contents
+ got_off
);
2975 rela
.r_info
= ELFNN_R_INFO (0,
2976 R_LARCH_TLS_DTPMODNN
);
2977 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2980 bfd_put_NN (output_bfd
, tls_block_off
,
2981 got
->contents
+ got_off
+ GOT_ENTRY_SIZE
);
2983 /* Dynamic resolved. */
2986 /* Dynamic relocate module id. */
2987 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
2988 R_LARCH_TLS_DTPMODNN
);
2989 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2991 /* Dynamic relocate offset of block. */
2992 rela
.r_offset
+= GOT_ENTRY_SIZE
;
2993 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
2994 R_LARCH_TLS_DTPRELNN
);
2995 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
2998 if (tls_type
& GOT_TLS_IE
)
3000 rela
.r_offset
= sec_addr (got
) + got_off
+ ie_off
;
3001 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3003 /* Local sym, used in exec, set module id 1. */
3004 if (!bfd_link_executable (info
))
3006 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN
);
3007 rela
.r_addend
= tls_block_off
;
3008 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
3011 bfd_put_NN (output_bfd
, tls_block_off
,
3012 got
->contents
+ got_off
+ ie_off
);
3014 /* Dynamic resolved. */
3017 /* Dynamic relocate offset of block. */
3018 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3019 R_LARCH_TLS_TPRELNN
);
3021 loongarch_elf_append_rela (output_bfd
, srel
, &rela
);
3026 relocation
= (got_off
& (~(bfd_vma
)1)) + (is_ie
? ie_off
: 0);
3030 /* New reloc types. */
3034 unresolved_reloc
= false;
3043 relocation
+= rel
->r_addend
;
3045 else if (resolved_dynly
)
3048 && (h
->plt
.offset
!= MINUS_ONE
3049 || ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
)
3050 && rel
->r_addend
== 0);
3051 if (h
&& h
->plt
.offset
== MINUS_ONE
3052 && ELF_ST_VISIBILITY (h
->other
) != STV_DEFAULT
)
3055 relocation
+= rel
->r_addend
;
3058 relocation
= sec_addr (plt
) + h
->plt
.offset
- pc
;
3063 case R_LARCH_ABS_HI20
:
3064 case R_LARCH_ABS_LO12
:
3065 case R_LARCH_ABS64_LO20
:
3066 case R_LARCH_ABS64_HI12
:
3067 BFD_ASSERT (!is_pic
);
3071 BFD_ASSERT (resolved_dynly
);
3075 else if (resolved_to_const
|| resolved_local
)
3077 relocation
+= rel
->r_addend
;
3079 else if (resolved_dynly
)
3081 unresolved_reloc
= false;
3082 BFD_ASSERT ((plt
&& h
&& h
->plt
.offset
!= MINUS_ONE
)
3083 && rel
->r_addend
== 0);
3084 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3089 case R_LARCH_PCALA_HI20
:
3090 unresolved_reloc
= false;
3091 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
3092 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3094 relocation
+= rel
->r_addend
;
3096 RELOCATE_CALC_PC32_HI20 (relocation
, pc
);
3100 case R_LARCH_PCALA_LO12
:
3101 /* Not support if sym_addr in 2k page edge.
3102 pcalau12i pc_hi20 (sym_addr)
3103 ld.w/d pc_lo12 (sym_addr)
3104 ld.w/d pc_lo12 (sym_addr + x)
3106 can not calc correct address
3107 if sym_addr < 0x800 && sym_addr + x >= 0x800. */
3109 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
3110 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3112 relocation
+= rel
->r_addend
;
3114 relocation
&= 0xfff;
3115 /* Signed extend. */
3116 relocation
= (relocation
^ 0x800) - 0x800;
3118 /* For 2G jump, generate pcalau12i, jirl. */
3119 /* If use jirl, turns to R_LARCH_B16. */
3120 uint32_t insn
= bfd_get (32, input_bfd
, contents
+ rel
->r_offset
);
3121 if ((insn
& 0x4c000000) == 0x4c000000)
3123 rel
->r_info
= ELFNN_R_INFO (r_symndx
, R_LARCH_B16
);
3124 howto
= loongarch_elf_rtype_to_howto (input_bfd
, R_LARCH_B16
);
3128 case R_LARCH_PCALA64_LO20
:
3129 case R_LARCH_PCALA64_HI12
:
3130 if (h
&& h
->plt
.offset
!= MINUS_ONE
)
3131 relocation
= sec_addr (plt
) + h
->plt
.offset
;
3133 relocation
+= rel
->r_addend
;
3135 RELOCATE_CALC_PC64_HI32 (relocation
, pc
);
3139 case R_LARCH_GOT_PC_HI20
:
3140 case R_LARCH_GOT_HI20
:
3141 /* Calc got offset. */
3143 unresolved_reloc
= false;
3144 BFD_ASSERT (rel
->r_addend
== 0);
3146 bfd_vma got_off
= 0;
3149 /* GOT ref or ifunc. */
3150 BFD_ASSERT (h
->got
.offset
!= MINUS_ONE
3151 || h
->type
== STT_GNU_IFUNC
);
3153 got_off
= h
->got
.offset
& (~(bfd_vma
)1);
3154 /* Hidden symbol not has got entry,
3155 * only got.plt entry so it is (plt - got). */
3156 if (h
->got
.offset
== MINUS_ONE
&& h
->type
== STT_GNU_IFUNC
)
3159 if (htab
->elf
.splt
!= NULL
)
3161 idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
)
3163 got_off
= sec_addr (htab
->elf
.sgotplt
)
3164 + GOTPLT_HEADER_SIZE
3165 + (idx
* GOT_ENTRY_SIZE
)
3166 - sec_addr (htab
->elf
.sgot
);
3170 idx
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
3171 got_off
= sec_addr (htab
->elf
.sgotplt
)
3172 + (idx
* GOT_ENTRY_SIZE
)
3173 - sec_addr (htab
->elf
.sgot
);
3177 if ((h
->got
.offset
& 1) == 0)
3179 /* We need to generate a R_LARCH_RELATIVE reloc once
3180 * in loongarch_elf_finish_dynamic_symbol or now,
3181 * call finish_dyn && nopic
3182 * or !call finish_dyn && pic. */
3183 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn
,
3184 bfd_link_pic (info
),
3186 && bfd_link_pic (info
)
3187 && SYMBOL_REFERENCES_LOCAL (info
, h
))
3189 Elf_Internal_Rela rela
;
3190 rela
.r_offset
= sec_addr (got
) + got_off
;
3191 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
3192 rela
.r_addend
= relocation
;
3193 loongarch_elf_append_rela (output_bfd
,
3194 htab
->elf
.srelgot
, &rela
);
3197 bfd_put_NN (output_bfd
, relocation
,
3198 got
->contents
+ got_off
);
3203 BFD_ASSERT (local_got_offsets
3204 && local_got_offsets
[r_symndx
] != MINUS_ONE
);
3206 got_off
= local_got_offsets
[r_symndx
] & (~(bfd_vma
)1);
3207 if ((local_got_offsets
[r_symndx
] & 1) == 0)
3209 if (bfd_link_pic (info
))
3211 Elf_Internal_Rela rela
;
3212 rela
.r_offset
= sec_addr (got
) + got_off
;
3213 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
3214 rela
.r_addend
= relocation
;
3215 loongarch_elf_append_rela (output_bfd
,
3216 htab
->elf
.srelgot
, &rela
);
3218 local_got_offsets
[r_symndx
] |= 1;
3220 bfd_put_NN (output_bfd
, relocation
, got
->contents
+ got_off
);
3223 relocation
= got_off
+ sec_addr (got
);
3226 if (r_type
== R_LARCH_GOT_PC_HI20
)
3227 RELOCATE_CALC_PC32_HI20 (relocation
, pc
);
3231 case R_LARCH_GOT_PC_LO12
:
3232 case R_LARCH_GOT64_PC_LO20
:
3233 case R_LARCH_GOT64_PC_HI12
:
3234 case R_LARCH_GOT_LO12
:
3235 case R_LARCH_GOT64_LO20
:
3236 case R_LARCH_GOT64_HI12
:
3238 unresolved_reloc
= false;
3241 got_off
= h
->got
.offset
& (~(bfd_vma
)1);
3243 got_off
= local_got_offsets
[r_symndx
] & (~(bfd_vma
)1);
3245 if (h
&& h
->got
.offset
== MINUS_ONE
&& h
->type
== STT_GNU_IFUNC
)
3248 if (htab
->elf
.splt
!= NULL
)
3249 idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
) / PLT_ENTRY_SIZE
;
3251 idx
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
3253 got_off
= sec_addr (htab
->elf
.sgotplt
)
3254 + GOTPLT_HEADER_SIZE
3255 + (idx
* GOT_ENTRY_SIZE
)
3256 - sec_addr (htab
->elf
.sgot
);
3258 relocation
= got_off
+ sec_addr (got
);
3261 if (r_type
== R_LARCH_GOT_PC_LO12
)
3262 relocation
&= (bfd_vma
)0xfff;
3263 else if (r_type
== R_LARCH_GOT64_PC_LO20
3264 || r_type
== R_LARCH_GOT64_PC_HI12
)
3265 RELOCATE_CALC_PC64_HI32 (relocation
, pc
);
3269 case R_LARCH_TLS_LE_HI20
:
3270 case R_LARCH_TLS_LE_LO12
:
3271 case R_LARCH_TLS_LE64_LO20
:
3272 case R_LARCH_TLS_LE64_HI12
:
3273 BFD_ASSERT (resolved_local
&& elf_hash_table (info
)->tls_sec
);
3275 relocation
-= elf_hash_table (info
)->tls_sec
->vma
;
3278 /* TLS IE LD/GD process separately is troublesome.
3279 When a symbol is both ie and LD/GD, h->got.off |= 1
3280 make only one type be relocated. We must use
3281 h->got.offset |= 1 and h->got.offset |= 2
3282 diff IE and LD/GD. And all (got_off & (~(bfd_vma)1))
3283 (IE LD/GD and reusable GOT reloc) must change to
3284 (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
3286 Now, LD and GD is both GOT_TLS_GD type, LD seems to
3288 case R_LARCH_TLS_IE_PC_HI20
:
3289 case R_LARCH_TLS_IE_HI20
:
3290 case R_LARCH_TLS_LD_PC_HI20
:
3291 case R_LARCH_TLS_LD_HI20
:
3292 case R_LARCH_TLS_GD_PC_HI20
:
3293 case R_LARCH_TLS_GD_HI20
:
3294 BFD_ASSERT (rel
->r_addend
== 0);
3295 unresolved_reloc
= false;
3297 if (r_type
== R_LARCH_TLS_IE_PC_HI20
3298 || r_type
== R_LARCH_TLS_IE_HI20
)
3301 bfd_vma got_off
= 0;
3304 got_off
= h
->got
.offset
;
3309 got_off
= local_got_offsets
[r_symndx
];
3310 local_got_offsets
[r_symndx
] |= 1;
3313 BFD_ASSERT (got_off
!= MINUS_ONE
);
3316 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
3317 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
3318 ie_off
= 2 * GOT_ENTRY_SIZE
;
3320 if ((got_off
& 1) == 0)
3322 Elf_Internal_Rela rela
;
3323 asection
*relgot
= htab
->elf
.srelgot
;
3324 bfd_vma tls_block_off
= 0;
3326 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3328 BFD_ASSERT (elf_hash_table (info
)->tls_sec
);
3329 tls_block_off
= relocation
3330 - elf_hash_table (info
)->tls_sec
->vma
;
3333 if (tls_type
& GOT_TLS_GD
)
3335 rela
.r_offset
= sec_addr (got
) + got_off
;
3337 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3339 /* Local sym, used in exec, set module id 1. */
3340 if (bfd_link_executable (info
))
3341 bfd_put_NN (output_bfd
, 1, got
->contents
+ got_off
);
3344 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN
);
3345 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3348 bfd_put_NN (output_bfd
, tls_block_off
,
3349 got
->contents
+ got_off
+ GOT_ENTRY_SIZE
);
3351 /* Dynamic resolved. */
3354 /* Dynamic relocate module id. */
3355 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3356 R_LARCH_TLS_DTPMODNN
);
3357 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3359 /* Dynamic relocate offset of block. */
3360 rela
.r_offset
+= GOT_ENTRY_SIZE
;
3361 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3362 R_LARCH_TLS_DTPRELNN
);
3363 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3366 if (tls_type
& GOT_TLS_IE
)
3368 rela
.r_offset
= sec_addr (got
) + got_off
+ ie_off
;
3369 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3371 /* Local sym, used in exec, set module id 1. */
3372 if (!bfd_link_executable (info
))
3374 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN
);
3375 rela
.r_addend
= tls_block_off
;
3376 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3379 bfd_put_NN (output_bfd
, tls_block_off
,
3380 got
->contents
+ got_off
+ ie_off
);
3382 /* Dynamic resolved. */
3385 /* Dynamic relocate offset of block. */
3386 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
,
3387 R_LARCH_TLS_TPRELNN
);
3389 loongarch_elf_append_rela (output_bfd
, relgot
, &rela
);
3393 relocation
= (got_off
& (~(bfd_vma
)1)) + sec_addr (got
)
3394 + (is_ie
? ie_off
: 0);
3396 if (r_type
== R_LARCH_TLS_LD_PC_HI20
3397 || r_type
== R_LARCH_TLS_GD_PC_HI20
3398 || r_type
== R_LARCH_TLS_IE_PC_HI20
)
3399 RELOCATE_CALC_PC32_HI20 (relocation
, pc
);
3403 case R_LARCH_TLS_IE_PC_LO12
:
3404 case R_LARCH_TLS_IE64_PC_LO20
:
3405 case R_LARCH_TLS_IE64_PC_HI12
:
3406 case R_LARCH_TLS_IE_LO12
:
3407 case R_LARCH_TLS_IE64_LO20
:
3408 case R_LARCH_TLS_IE64_HI12
:
3409 unresolved_reloc
= false;
3412 relocation
= sec_addr (got
) + (h
->got
.offset
& (~(bfd_vma
)3));
3414 relocation
= sec_addr (got
)
3415 + (local_got_offsets
[r_symndx
] & (~(bfd_vma
)3));
3417 tls_type
= _bfd_loongarch_elf_tls_type (input_bfd
, h
, r_symndx
);
3418 /* Use both TLS_GD and TLS_IE. */
3419 if ((tls_type
& GOT_TLS_GD
) && (tls_type
& GOT_TLS_IE
))
3420 relocation
+= 2 * GOT_ENTRY_SIZE
;
3422 if (r_type
== R_LARCH_TLS_IE_PC_LO12
)
3423 relocation
&= (bfd_vma
)0xfff;
3424 else if (r_type
== R_LARCH_TLS_IE64_PC_LO20
3425 || r_type
== R_LARCH_TLS_IE64_PC_HI12
)
3426 RELOCATE_CALC_PC64_HI32 (relocation
, pc
);
3442 /* 'unresolved_reloc' means we haven't done it yet.
3443 We need help of dynamic linker to fix this memory location up. */
3444 if (!unresolved_reloc
)
3447 if (_bfd_elf_section_offset (output_bfd
, info
, input_section
,
3448 rel
->r_offset
) == MINUS_ONE
)
3449 /* WHY? May because it's invalid so skip checking.
3450 But why dynamic reloc a invalid section? */
3453 if (input_section
->output_section
->flags
& SEC_DEBUGGING
)
3455 fatal
= (loongarch_reloc_is_fatal
3456 (info
, input_bfd
, input_section
, rel
, howto
,
3457 bfd_reloc_dangerous
, is_undefweak
, name
,
3458 "Seems dynamic linker not process "
3459 "sections 'SEC_DEBUGGING'."));
3464 if ((info
->flags
& DF_TEXTREL
) == 0)
3465 if (input_section
->output_section
->flags
& SEC_READONLY
)
3466 info
->flags
|= DF_TEXTREL
;
3473 loongarch_record_one_reloc (input_bfd
, input_section
, r_type
,
3474 rel
->r_offset
, sym
, h
, rel
->r_addend
);
3476 if (r
!= bfd_reloc_continue
)
3477 r
= perform_relocation (rel
, input_section
, howto
, relocation
,
3478 input_bfd
, contents
);
3482 case bfd_reloc_dangerous
:
3483 case bfd_reloc_continue
:
3487 case bfd_reloc_overflow
:
3488 /* Overflow value can't be filled in. */
3489 loongarch_dump_reloc_record (info
->callbacks
->info
);
3490 info
->callbacks
->reloc_overflow
3491 (info
, h
? &h
->root
: NULL
, name
, howto
->name
, rel
->r_addend
,
3492 input_bfd
, input_section
, rel
->r_offset
);
3495 case bfd_reloc_outofrange
:
3496 /* Stack state incorrect. */
3497 loongarch_dump_reloc_record (info
->callbacks
->info
);
3498 info
->callbacks
->info
3499 ("%X%H: Internal stack state is incorrect.\n"
3500 "Want to push to full stack or pop from empty stack?\n",
3501 input_bfd
, input_section
, rel
->r_offset
);
3504 case bfd_reloc_notsupported
:
3505 info
->callbacks
->info ("%X%H: Unknown relocation type.\n", input_bfd
,
3506 input_section
, rel
->r_offset
);
3510 info
->callbacks
->info ("%X%H: Internal: unknown error.\n", input_bfd
,
3511 input_section
, rel
->r_offset
);
3521 /* Finish up dynamic symbol handling. We set the contents of various
3522 dynamic sections here. */
3525 loongarch_elf_finish_dynamic_symbol (bfd
*output_bfd
,
3526 struct bfd_link_info
*info
,
3527 struct elf_link_hash_entry
*h
,
3528 Elf_Internal_Sym
*sym
)
3530 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
3531 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
3532 asection
*rela_dyn
= bfd_get_section_by_name (output_bfd
, ".rela.dyn");
3533 struct bfd_link_order
*lo
= NULL
;
3534 Elf_Internal_Rela
*slot
= NULL
, *last_slot
= NULL
;
3537 lo
= rela_dyn
->map_head
.link_order
;
3539 if (h
->plt
.offset
!= MINUS_ONE
)
3542 asection
*plt
, *gotplt
, *relplt
;
3543 bfd_vma got_address
;
3544 uint32_t plt_entry
[PLT_ENTRY_INSNS
];
3546 Elf_Internal_Rela rela
;
3547 asection
*rela_sec
= NULL
;
3551 BFD_ASSERT ((h
->type
== STT_GNU_IFUNC
3552 && SYMBOL_REFERENCES_LOCAL (info
, h
))
3553 || h
->dynindx
!= -1);
3555 plt
= htab
->elf
.splt
;
3556 gotplt
= htab
->elf
.sgotplt
;
3557 if (h
->type
== STT_GNU_IFUNC
&& SYMBOL_REFERENCES_LOCAL (info
, h
))
3558 relplt
= htab
->elf
.srelgot
;
3560 relplt
= htab
->elf
.srelplt
;
3561 plt_idx
= (h
->plt
.offset
- PLT_HEADER_SIZE
) / PLT_ENTRY_SIZE
;
3563 sec_addr (gotplt
) + GOTPLT_HEADER_SIZE
+ plt_idx
* GOT_ENTRY_SIZE
;
3565 else /* if (htab->elf.iplt) */
3567 BFD_ASSERT (h
->type
== STT_GNU_IFUNC
3568 && SYMBOL_REFERENCES_LOCAL (info
, h
));
3570 plt
= htab
->elf
.iplt
;
3571 gotplt
= htab
->elf
.igotplt
;
3572 relplt
= htab
->elf
.irelplt
;
3573 plt_idx
= h
->plt
.offset
/ PLT_ENTRY_SIZE
;
3574 got_address
= sec_addr (gotplt
) + plt_idx
* GOT_ENTRY_SIZE
;
3577 /* Find out where the .plt entry should go. */
3578 loc
= plt
->contents
+ h
->plt
.offset
;
3580 /* Fill in the PLT entry itself. */
3581 if (!loongarch_make_plt_entry (got_address
,
3582 sec_addr (plt
) + h
->plt
.offset
,
3586 for (i
= 0; i
< PLT_ENTRY_INSNS
; i
++)
3587 bfd_put_32 (output_bfd
, plt_entry
[i
], loc
+ 4 * i
);
3589 /* Fill in the initial value of the got.plt entry. */
3590 loc
= gotplt
->contents
+ (got_address
- sec_addr (gotplt
));
3591 bfd_put_NN (output_bfd
, sec_addr (plt
), loc
);
3593 rela
.r_offset
= got_address
;
3595 /* TRUE if this is a PLT reference to a local IFUNC. */
3596 if (PLT_LOCAL_IFUNC_P (info
, h
)
3597 && (relplt
== htab
->elf
.srelgot
3598 || relplt
== htab
->elf
.irelplt
))
3600 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
3601 rela
.r_addend
= (h
->root
.u
.def
.value
3602 + h
->root
.u
.def
.section
->output_section
->vma
3603 + h
->root
.u
.def
.section
->output_offset
);
3605 /* Find the space after dyn sort. */
3606 while (slot
== last_slot
|| slot
->r_offset
!= 0)
3608 if (slot
!= last_slot
)
3614 BFD_ASSERT (lo
!= NULL
);
3615 rela_sec
= lo
->u
.indirect
.section
;
3618 slot
= (Elf_Internal_Rela
*)rela_sec
->contents
;
3619 last_slot
= (Elf_Internal_Rela
*)(rela_sec
->contents
+
3623 bed
->s
->swap_reloca_out (output_bfd
, &rela
, (bfd_byte
*)slot
);
3624 rela_sec
->reloc_count
++;
3628 /* Fill in the entry in the rela.plt section. */
3629 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_JUMP_SLOT
);
3631 loc
= relplt
->contents
+ plt_idx
* sizeof (ElfNN_External_Rela
);
3632 bed
->s
->swap_reloca_out (output_bfd
, &rela
, loc
);
3635 if (!h
->def_regular
)
3637 /* Mark the symbol as undefined, rather than as defined in
3638 the .plt section. Leave the value alone. */
3639 sym
->st_shndx
= SHN_UNDEF
;
3640 /* If the symbol is weak, we do need to clear the value.
3641 Otherwise, the PLT entry would provide a definition for
3642 the symbol even if the symbol wasn't defined anywhere,
3643 and so the symbol would never be NULL. */
3644 if (!h
->ref_regular_nonweak
)
3649 if (h
->got
.offset
!= MINUS_ONE
3650 /* TLS got entry have been handled in elf_relocate_section. */
3651 && !(loongarch_elf_hash_entry (h
)->tls_type
& (GOT_TLS_GD
| GOT_TLS_IE
))
3652 /* Have allocated got entry but not allocated rela before. */
3653 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info
, h
))
3655 asection
*sgot
, *srela
;
3656 Elf_Internal_Rela rela
;
3657 bfd_vma off
= h
->got
.offset
& ~(bfd_vma
)1;
3659 /* This symbol has an entry in the GOT. Set it up. */
3660 sgot
= htab
->elf
.sgot
;
3661 srela
= htab
->elf
.srelgot
;
3662 BFD_ASSERT (sgot
&& srela
);
3664 rela
.r_offset
= sec_addr (sgot
) + off
;
3667 && h
->type
== STT_GNU_IFUNC
)
3669 if(h
->plt
.offset
== MINUS_ONE
)
3671 if (htab
->elf
.splt
== NULL
)
3672 srela
= htab
->elf
.irelplt
;
3674 if (SYMBOL_REFERENCES_LOCAL (info
, h
))
3676 asection
*sec
= h
->root
.u
.def
.section
;
3677 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_IRELATIVE
);
3678 rela
.r_addend
= h
->root
.u
.def
.value
+ sec
->output_section
->vma
3679 + sec
->output_offset
;
3680 bfd_put_NN (output_bfd
, 0, sgot
->contents
+ off
);
3684 BFD_ASSERT (h
->dynindx
!= -1);
3685 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
3687 bfd_put_NN (output_bfd
, (bfd_vma
) 0, sgot
->contents
+ off
);
3690 else if(bfd_link_pic (info
))
3692 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
3694 bfd_put_NN (output_bfd
, rela
.r_addend
, sgot
->contents
+ off
);
3699 /* For non-shared object, we can't use .got.plt, which
3700 contains the real function address if we need pointer
3701 equality. We load the GOT entry with the PLT entry. */
3702 plt
= htab
->elf
.splt
? htab
->elf
.splt
: htab
->elf
.iplt
;
3703 bfd_put_NN (output_bfd
,
3704 (plt
->output_section
->vma
3705 + plt
->output_offset
3707 sgot
->contents
+ off
);
3711 else if (bfd_link_pic (info
) && SYMBOL_REFERENCES_LOCAL (info
, h
))
3713 asection
*sec
= h
->root
.u
.def
.section
;
3714 rela
.r_info
= ELFNN_R_INFO (0, R_LARCH_RELATIVE
);
3715 rela
.r_addend
= (h
->root
.u
.def
.value
+ sec
->output_section
->vma
3716 + sec
->output_offset
);
3720 BFD_ASSERT (h
->dynindx
!= -1);
3721 rela
.r_info
= ELFNN_R_INFO (h
->dynindx
, R_LARCH_NN
);
3725 loongarch_elf_append_rela (output_bfd
, srela
, &rela
);
3728 /* Mark some specially defined symbols as absolute. */
3729 if (h
== htab
->elf
.hdynamic
|| h
== htab
->elf
.hgot
|| h
== htab
->elf
.hplt
)
3730 sym
->st_shndx
= SHN_ABS
;
3735 /* Finish up the dynamic sections. */
3738 loongarch_finish_dyn (bfd
*output_bfd
, struct bfd_link_info
*info
, bfd
*dynobj
,
3741 struct loongarch_elf_link_hash_table
*htab
= loongarch_elf_hash_table (info
);
3742 const struct elf_backend_data
*bed
= get_elf_backend_data (output_bfd
);
3743 size_t dynsize
= bed
->s
->sizeof_dyn
, skipped_size
= 0;
3744 bfd_byte
*dyncon
, *dynconend
;
3746 dynconend
= sdyn
->contents
+ sdyn
->size
;
3747 for (dyncon
= sdyn
->contents
; dyncon
< dynconend
; dyncon
+= dynsize
)
3749 Elf_Internal_Dyn dyn
;
3753 bed
->s
->swap_dyn_in (dynobj
, dyncon
, &dyn
);
3758 s
= htab
->elf
.sgotplt
;
3759 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3762 s
= htab
->elf
.srelplt
;
3763 dyn
.d_un
.d_ptr
= s
->output_section
->vma
+ s
->output_offset
;
3766 s
= htab
->elf
.srelplt
;
3767 dyn
.d_un
.d_val
= s
->size
;
3770 if ((info
->flags
& DF_TEXTREL
) == 0)
3774 if ((info
->flags
& DF_TEXTREL
) == 0)
3775 dyn
.d_un
.d_val
&= ~DF_TEXTREL
;
3779 skipped_size
+= dynsize
;
3781 bed
->s
->swap_dyn_out (output_bfd
, &dyn
, dyncon
- skipped_size
);
3783 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
3784 memset (dyncon
- skipped_size
, 0, skipped_size
);
3788 /* Finish up local dynamic symbol handling. We set the contents of
3789 various dynamic sections here. */
3792 elfNN_loongarch_finish_local_dynamic_symbol (void **slot
, void *inf
)
3794 struct elf_link_hash_entry
*h
= (struct elf_link_hash_entry
*) *slot
;
3795 struct bfd_link_info
*info
= (struct bfd_link_info
*) inf
;
3797 return loongarch_elf_finish_dynamic_symbol (info
->output_bfd
, info
, h
, NULL
);
3801 loongarch_elf_finish_dynamic_sections (bfd
*output_bfd
,
3802 struct bfd_link_info
*info
)
3805 asection
*sdyn
, *plt
, *gotplt
= NULL
;
3806 struct loongarch_elf_link_hash_table
*htab
;
3808 htab
= loongarch_elf_hash_table (info
);
3810 dynobj
= htab
->elf
.dynobj
;
3811 sdyn
= bfd_get_linker_section (dynobj
, ".dynamic");
3813 if (elf_hash_table (info
)->dynamic_sections_created
)
3815 BFD_ASSERT (htab
->elf
.splt
&& sdyn
);
3817 if (!loongarch_finish_dyn (output_bfd
, info
, dynobj
, sdyn
))
3821 plt
= htab
->elf
.splt
;
3822 gotplt
= htab
->elf
.sgotplt
;
3824 if (plt
&& 0 < plt
->size
)
3827 uint32_t plt_header
[PLT_HEADER_INSNS
];
3828 if (!loongarch_make_plt_header (sec_addr (gotplt
), sec_addr (plt
),
3832 for (i
= 0; i
< PLT_HEADER_INSNS
; i
++)
3833 bfd_put_32 (output_bfd
, plt_header
[i
], plt
->contents
+ 4 * i
);
3835 elf_section_data (plt
->output_section
)->this_hdr
.sh_entsize
=
3839 if (htab
->elf
.sgotplt
)
3841 asection
*output_section
= htab
->elf
.sgotplt
->output_section
;
3843 if (bfd_is_abs_section (output_section
))
3845 _bfd_error_handler (_("discarded output section: `%pA'"),
3850 if (0 < htab
->elf
.sgotplt
->size
)
3852 /* Write the first two entries in .got.plt, needed for the dynamic
3854 bfd_put_NN (output_bfd
, MINUS_ONE
, htab
->elf
.sgotplt
->contents
);
3856 bfd_put_NN (output_bfd
, (bfd_vma
) 0,
3857 htab
->elf
.sgotplt
->contents
+ GOT_ENTRY_SIZE
);
3860 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
3865 asection
*output_section
= htab
->elf
.sgot
->output_section
;
3867 if (0 < htab
->elf
.sgot
->size
)
3869 /* Set the first entry in the global offset table to the address of
3870 the dynamic section. */
3871 bfd_vma val
= sdyn
? sec_addr (sdyn
) : 0;
3872 bfd_put_NN (output_bfd
, val
, htab
->elf
.sgot
->contents
);
3875 elf_section_data (output_section
)->this_hdr
.sh_entsize
= GOT_ENTRY_SIZE
;
3878 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
3879 htab_traverse (htab
->loc_hash_table
,
3880 (void *) elfNN_loongarch_finish_local_dynamic_symbol
, info
);
3885 /* Return address for Ith PLT stub in section PLT, for relocation REL
3886 or (bfd_vma) -1 if it should not be included. */
3889 loongarch_elf_plt_sym_val (bfd_vma i
, const asection
*plt
,
3890 const arelent
*rel ATTRIBUTE_UNUSED
)
3892 return plt
->vma
+ PLT_HEADER_SIZE
+ i
* PLT_ENTRY_SIZE
;
3895 static enum elf_reloc_type_class
3896 loongarch_reloc_type_class (const struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
3897 const asection
*rel_sec ATTRIBUTE_UNUSED
,
3898 const Elf_Internal_Rela
*rela
)
3900 struct loongarch_elf_link_hash_table
*htab
;
3901 htab
= loongarch_elf_hash_table (info
);
3903 if (htab
->elf
.dynsym
!= NULL
&& htab
->elf
.dynsym
->contents
!= NULL
)
3905 /* Check relocation against STT_GNU_IFUNC symbol if there are
3907 bfd
*abfd
= info
->output_bfd
;
3908 const struct elf_backend_data
*bed
= get_elf_backend_data (abfd
);
3909 unsigned long r_symndx
= ELFNN_R_SYM (rela
->r_info
);
3910 if (r_symndx
!= STN_UNDEF
)
3912 Elf_Internal_Sym sym
;
3913 if (!bed
->s
->swap_symbol_in (abfd
,
3914 htab
->elf
.dynsym
->contents
3915 + r_symndx
* bed
->s
->sizeof_sym
,
3918 /* xgettext:c-format */
3919 _bfd_error_handler (_("%pB symbol number %lu references"
3920 " nonexistent SHT_SYMTAB_SHNDX section"),
3922 /* Ideally an error class should be returned here. */
3924 else if (ELF_ST_TYPE (sym
.st_info
) == STT_GNU_IFUNC
)
3925 return reloc_class_ifunc
;
3929 switch (ELFNN_R_TYPE (rela
->r_info
))
3931 case R_LARCH_IRELATIVE
:
3932 return reloc_class_ifunc
;
3933 case R_LARCH_RELATIVE
:
3934 return reloc_class_relative
;
3935 case R_LARCH_JUMP_SLOT
:
3936 return reloc_class_plt
;
3938 return reloc_class_copy
;
3940 return reloc_class_normal
;
3944 /* Copy the extra info we tack onto an elf_link_hash_entry. */
3947 loongarch_elf_copy_indirect_symbol (struct bfd_link_info
*info
,
3948 struct elf_link_hash_entry
*dir
,
3949 struct elf_link_hash_entry
*ind
)
3951 struct elf_link_hash_entry
*edir
, *eind
;
3956 if (eind
->dyn_relocs
!= NULL
)
3958 if (edir
->dyn_relocs
!= NULL
)
3960 struct elf_dyn_relocs
**pp
;
3961 struct elf_dyn_relocs
*p
;
3963 /* Add reloc counts against the indirect sym to the direct sym
3964 list. Merge any entries against the same section. */
3965 for (pp
= &eind
->dyn_relocs
; (p
= *pp
) != NULL
;)
3967 struct elf_dyn_relocs
*q
;
3969 for (q
= edir
->dyn_relocs
; q
!= NULL
; q
= q
->next
)
3970 if (q
->sec
== p
->sec
)
3972 q
->pc_count
+= p
->pc_count
;
3973 q
->count
+= p
->count
;
3980 *pp
= edir
->dyn_relocs
;
3983 edir
->dyn_relocs
= eind
->dyn_relocs
;
3984 eind
->dyn_relocs
= NULL
;
3987 if (ind
->root
.type
== bfd_link_hash_indirect
&& dir
->got
.refcount
< 0)
3989 loongarch_elf_hash_entry(edir
)->tls_type
3990 = loongarch_elf_hash_entry(eind
)->tls_type
;
3991 loongarch_elf_hash_entry(eind
)->tls_type
= GOT_UNKNOWN
;
3993 _bfd_elf_link_hash_copy_indirect (info
, dir
, ind
);
3996 #define PRSTATUS_SIZE 0x1d8
3997 #define PRSTATUS_OFFSET_PR_CURSIG 0xc
3998 #define PRSTATUS_OFFSET_PR_PID 0x20
3999 #define ELF_GREGSET_T_SIZE 0x168
4000 #define PRSTATUS_OFFSET_PR_REG 0x70
4002 /* Support for core dump NOTE sections. */
4005 loongarch_elf_grok_prstatus (bfd
*abfd
, Elf_Internal_Note
*note
)
4007 switch (note
->descsz
)
4012 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
4015 elf_tdata (abfd
)->core
->signal
=
4016 bfd_get_16 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_CURSIG
);
4019 elf_tdata (abfd
)->core
->lwpid
=
4020 bfd_get_32 (abfd
, note
->descdata
+ PRSTATUS_OFFSET_PR_PID
);
4024 /* Make a ".reg/999" section. */
4025 return _bfd_elfcore_make_pseudosection (abfd
, ".reg", ELF_GREGSET_T_SIZE
,
4027 + PRSTATUS_OFFSET_PR_REG
);
4030 #define PRPSINFO_SIZE 0x88
4031 #define PRPSINFO_OFFSET_PR_PID 0x18
4032 #define PRPSINFO_OFFSET_PR_FNAME 0x28
4033 #define PRPSINFO_SIZEOF_PR_FNAME 0x10
4034 #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
4035 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
4038 loongarch_elf_grok_psinfo (bfd
*abfd
, Elf_Internal_Note
*note
)
4040 switch (note
->descsz
)
4045 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
4048 elf_tdata (abfd
)->core
->pid
=
4049 bfd_get_32 (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PID
);
4052 elf_tdata (abfd
)->core
->program
=
4053 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_FNAME
,
4054 PRPSINFO_SIZEOF_PR_FNAME
);
4057 elf_tdata (abfd
)->core
->command
=
4058 _bfd_elfcore_strndup (abfd
, note
->descdata
+ PRPSINFO_OFFSET_PR_PS_ARGS
,
4059 PRPSINFO_SIZEOF_PR_PS_ARGS
);
4063 /* Note that for some reason, a spurious space is tacked
4064 onto the end of the args in some (at least one anyway)
4065 implementations, so strip it off if it exists. */
4068 char *command
= elf_tdata (abfd
)->core
->command
;
4069 int n
= strlen (command
);
4071 if (0 < n
&& command
[n
- 1] == ' ')
4072 command
[n
- 1] = '\0';
4078 /* Set the right mach type. */
4080 loongarch_elf_object_p (bfd
*abfd
)
4082 /* There are only two mach types in LoongArch currently. */
4083 if (strcmp (abfd
->xvec
->name
, "elf64-loongarch") == 0)
4084 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch64
);
4086 bfd_default_set_arch_mach (abfd
, bfd_arch_loongarch
, bfd_mach_loongarch32
);
4091 loongarch_elf_gc_mark_hook (asection
*sec
, struct bfd_link_info
*info
,
4092 Elf_Internal_Rela
*rel
,
4093 struct elf_link_hash_entry
*h
,
4094 Elf_Internal_Sym
*sym
)
4097 switch (ELFNN_R_TYPE (rel
->r_info
))
4099 case R_LARCH_GNU_VTINHERIT
:
4100 case R_LARCH_GNU_VTENTRY
:
4104 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
4107 /* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For
4108 executable PLT slots where the executable never takes the address of those
4109 functions, the function symbols are not added to the hash table. */
4112 elf_loongarch64_hash_symbol (struct elf_link_hash_entry
*h
)
4114 if (h
->plt
.offset
!= (bfd_vma
) -1
4116 && !h
->pointer_equality_needed
)
4119 return _bfd_elf_hash_symbol (h
);
4122 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
4123 #define TARGET_LITTLE_NAME "elfNN-loongarch"
4124 #define ELF_ARCH bfd_arch_loongarch
4125 #define ELF_TARGET_ID LARCH_ELF_DATA
4126 #define ELF_MACHINE_CODE EM_LOONGARCH
4127 #define ELF_MAXPAGESIZE 0x4000
4128 #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
4129 #define bfd_elfNN_bfd_link_hash_table_create \
4130 loongarch_elf_link_hash_table_create
4131 #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
4132 #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
4133 #define elf_info_to_howto loongarch_info_to_howto_rela
4134 #define bfd_elfNN_bfd_merge_private_bfd_data \
4135 elfNN_loongarch_merge_private_bfd_data
4137 #define elf_backend_reloc_type_class loongarch_reloc_type_class
4138 #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
4139 #define elf_backend_create_dynamic_sections \
4140 loongarch_elf_create_dynamic_sections
4141 #define elf_backend_check_relocs loongarch_elf_check_relocs
4142 #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
4143 #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
4144 #define elf_backend_relocate_section loongarch_elf_relocate_section
4145 #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
4146 #define elf_backend_finish_dynamic_sections \
4147 loongarch_elf_finish_dynamic_sections
4148 #define elf_backend_object_p loongarch_elf_object_p
4149 #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
4150 #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
4151 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
4152 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
4153 #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
4155 #include "elfNN-target.h"