Fix whitespace snafu in tc-riscv.c
[binutils-gdb.git] / bfd / elfnn-loongarch.c
blob024c5d4cd96ce822462ad3f26be432ba08e12cd9
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/>. */
21 #include "ansidecl.h"
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #define ARCH_SIZE NN
26 #include "elf-bfd.h"
27 #include "objalloc.h"
28 #include "elf/loongarch.h"
29 #include "elfxx-loongarch.h"
30 #include "opcode/loongarch.h"
32 static bool
33 loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
34 Elf_Internal_Rela *dst)
36 cache_ptr->howto = loongarch_elf_rtype_to_howto (abfd,
37 ELFNN_R_TYPE (dst->r_info));
38 return cache_ptr->howto != NULL;
41 /* LoongArch ELF linker hash entry. */
42 struct loongarch_elf_link_hash_entry
44 struct elf_link_hash_entry elf;
46 #define GOT_UNKNOWN 0
47 #define GOT_NORMAL 1
48 #define GOT_TLS_GD 2
49 #define GOT_TLS_IE 4
50 #define GOT_TLS_LE 8
51 char tls_type;
54 #define loongarch_elf_hash_entry(ent) \
55 ((struct loongarch_elf_link_hash_entry *) (ent))
57 struct _bfd_loongarch_elf_obj_tdata
59 struct elf_obj_tdata root;
61 /* The tls_type for each local got entry. */
62 char *local_got_tls_type;
65 #define _bfd_loongarch_elf_tdata(abfd) \
66 ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
68 #define _bfd_loongarch_elf_local_got_tls_type(abfd) \
69 (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
71 #define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
72 (*((h) != NULL \
73 ? &loongarch_elf_hash_entry (h)->tls_type \
74 : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
76 #define is_loongarch_elf(bfd) \
77 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
78 && elf_tdata (bfd) != NULL \
79 && elf_object_id (bfd) == LARCH_ELF_DATA)
81 struct loongarch_elf_link_hash_table
83 struct elf_link_hash_table elf;
85 /* Short-cuts to get to dynamic linker sections. */
86 asection *sdyntdata;
88 /* Small local sym to section mapping cache. */
89 struct sym_cache sym_cache;
91 /* Used by local STT_GNU_IFUNC symbols. */
92 htab_t loc_hash_table;
93 void *loc_hash_memory;
95 /* The max alignment of output sections. */
96 bfd_vma max_alignment;
98 /* The data segment phase, don't relax the section
99 when it is exp_seg_relro_adjust. */
100 int *data_segment_phase;
103 /* Get the LoongArch ELF linker hash table from a link_info structure. */
104 #define loongarch_elf_hash_table(p) \
105 (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
106 ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
107 : NULL)
109 #define MINUS_ONE ((bfd_vma) 0 - 1)
111 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
113 #define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
114 #define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
116 #define PLT_HEADER_INSNS 8
117 #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
119 #define PLT_ENTRY_INSNS 4
120 #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
122 #define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
124 #define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
126 #define elf_backend_want_got_plt 1
128 #define elf_backend_plt_readonly 1
130 #define elf_backend_want_plt_sym 1
131 #define elf_backend_plt_alignment 4
132 #define elf_backend_can_gc_sections 1
133 #define elf_backend_can_refcount 1
134 #define elf_backend_want_got_sym 1
136 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
138 #define elf_backend_want_dynrelro 1
139 #define elf_backend_rela_normal 1
140 #define elf_backend_default_execstack 0
142 /* Generate a PLT header. */
144 static bool
145 loongarch_make_plt_header (bfd_vma got_plt_addr, bfd_vma plt_header_addr,
146 uint32_t *entry)
148 bfd_vma pcrel = got_plt_addr - plt_header_addr;
149 bfd_vma hi, lo;
151 if (pcrel + 0x80000800 > 0xffffffff)
153 _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
154 bfd_set_error (bfd_error_bad_value);
155 return false;
157 hi = ((pcrel + 0x800) >> 12) & 0xfffff;
158 lo = pcrel & 0xfff;
160 /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
161 sub.[wd] $t1, $t1, $t3
162 ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
163 addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
164 addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
165 srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
166 ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
167 jirl $r0, $t3, 0 */
169 if (GOT_ENTRY_SIZE == 8)
171 entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
172 entry[1] = 0x0011bdad;
173 entry[2] = 0x28c001cf | (lo & 0xfff) << 10;
174 entry[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
175 entry[4] = 0x02c001cc | (lo & 0xfff) << 10;
176 entry[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
177 entry[6] = 0x28c0018c | GOT_ENTRY_SIZE << 10;
178 entry[7] = 0x4c0001e0;
180 else
182 entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
183 entry[1] = 0x00113dad;
184 entry[2] = 0x288001cf | (lo & 0xfff) << 10;
185 entry[3] = 0x028001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
186 entry[4] = 0x028001cc | (lo & 0xfff) << 10;
187 entry[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
188 entry[6] = 0x2880018c | GOT_ENTRY_SIZE << 10;
189 entry[7] = 0x4c0001e0;
191 return true;
194 /* Generate a PLT entry. */
196 static bool
197 loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, bfd_vma plt_entry_addr,
198 uint32_t *entry)
200 bfd_vma pcrel = got_plt_entry_addr - plt_entry_addr;
201 bfd_vma hi, lo;
203 if (pcrel + 0x80000800 > 0xffffffff)
205 _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
206 bfd_set_error (bfd_error_bad_value);
207 return false;
209 hi = ((pcrel + 0x800) >> 12) & 0xfffff;
210 lo = pcrel & 0xfff;
212 entry[0] = 0x1c00000f | (hi & 0xfffff) << 5;
213 entry[1] = ((GOT_ENTRY_SIZE == 8 ? 0x28c001ef : 0x288001ef)
214 | (lo & 0xfff) << 10);
215 entry[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
216 entry[3] = 0x03400000; /* nop */
218 return true;
221 /* Create an entry in an LoongArch ELF linker hash table. */
223 static struct bfd_hash_entry *
224 link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
225 const char *string)
227 struct loongarch_elf_link_hash_entry *eh;
229 /* Allocate the structure if it has not already been allocated by a
230 subclass. */
231 if (entry == NULL)
233 entry = bfd_hash_allocate (table, sizeof (*eh));
234 if (entry == NULL)
235 return entry;
238 /* Call the allocation method of the superclass. */
239 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
240 if (entry != NULL)
242 eh = (struct loongarch_elf_link_hash_entry *) entry;
243 eh->tls_type = GOT_UNKNOWN;
246 return entry;
249 /* Compute a hash of a local hash entry. We use elf_link_hash_entry
250 for local symbol so that we can handle local STT_GNU_IFUNC symbols
251 as global symbol. We reuse indx and dynstr_index for local symbol
252 hash since they aren't used by global symbols in this backend. */
254 static hashval_t
255 elfNN_loongarch_local_htab_hash (const void *ptr)
257 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr;
258 return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
261 /* Compare local hash entries. */
263 static int
264 elfNN_loongarch_local_htab_eq (const void *ptr1, const void *ptr2)
266 struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1;
267 struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2;
269 return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
272 /* Find and/or create a hash entry for local symbol. */
273 static struct elf_link_hash_entry *
274 elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table *htab,
275 bfd *abfd, const Elf_Internal_Rela *rel,
276 bool create)
278 struct loongarch_elf_link_hash_entry e, *ret;
279 asection *sec = abfd->sections;
280 hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, ELFNN_R_SYM (rel->r_info));
281 void **slot;
283 e.elf.indx = sec->id;
284 e.elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
285 slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
286 create ? INSERT : NO_INSERT);
288 if (!slot)
289 return NULL;
291 if (*slot)
293 ret = (struct loongarch_elf_link_hash_entry *) *slot;
294 return &ret->elf;
297 ret = ((struct loongarch_elf_link_hash_entry *)
298 objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
299 sizeof (struct loongarch_elf_link_hash_entry)));
300 if (ret)
302 memset (ret, 0, sizeof (*ret));
303 ret->elf.indx = sec->id;
304 ret->elf.pointer_equality_needed = 0;
305 ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
306 ret->elf.dynindx = -1;
307 ret->elf.needs_plt = 0;
308 ret->elf.plt.refcount = -1;
309 ret->elf.got.refcount = -1;
310 ret->elf.def_dynamic = 0;
311 ret->elf.def_regular = 1;
312 ret->elf.ref_dynamic = 0; /* This should be always 0 for local. */
313 ret->elf.ref_regular = 0;
314 ret->elf.forced_local = 1;
315 ret->elf.root.type = bfd_link_hash_defined;
316 *slot = ret;
318 return &ret->elf;
321 /* Destroy an LoongArch elf linker hash table. */
323 static void
324 elfNN_loongarch_link_hash_table_free (bfd *obfd)
326 struct loongarch_elf_link_hash_table *ret;
327 ret = (struct loongarch_elf_link_hash_table *) obfd->link.hash;
329 if (ret->loc_hash_table)
330 htab_delete (ret->loc_hash_table);
331 if (ret->loc_hash_memory)
332 objalloc_free ((struct objalloc *) ret->loc_hash_memory);
334 _bfd_elf_link_hash_table_free (obfd);
337 /* Create a LoongArch ELF linker hash table. */
339 static struct bfd_link_hash_table *
340 loongarch_elf_link_hash_table_create (bfd *abfd)
342 struct loongarch_elf_link_hash_table *ret;
343 bfd_size_type amt = sizeof (struct loongarch_elf_link_hash_table);
345 ret = (struct loongarch_elf_link_hash_table *) bfd_zmalloc (amt);
346 if (ret == NULL)
347 return NULL;
349 if (!_bfd_elf_link_hash_table_init
350 (&ret->elf, abfd, link_hash_newfunc,
351 sizeof (struct loongarch_elf_link_hash_entry), LARCH_ELF_DATA))
353 free (ret);
354 return NULL;
357 ret->max_alignment = MINUS_ONE;
359 ret->loc_hash_table = htab_try_create (1024, elfNN_loongarch_local_htab_hash,
360 elfNN_loongarch_local_htab_eq, NULL);
361 ret->loc_hash_memory = objalloc_create ();
362 if (!ret->loc_hash_table || !ret->loc_hash_memory)
364 elfNN_loongarch_link_hash_table_free (abfd);
365 return NULL;
367 ret->elf.root.hash_table_free = elfNN_loongarch_link_hash_table_free;
369 return &ret->elf.root;
372 /* Merge backend specific data from an object file to the output
373 object file when linking. */
375 static bool
376 elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
378 bfd *obfd = info->output_bfd;
379 flagword in_flags = elf_elfheader (ibfd)->e_flags;
380 flagword out_flags = elf_elfheader (obfd)->e_flags;
382 if (!is_loongarch_elf (ibfd) || !is_loongarch_elf (obfd))
383 return true;
385 if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
387 _bfd_error_handler (_("%pB: ABI is incompatible with that of "
388 "the selected emulation:\n"
389 " target emulation `%s' does not match `%s'"),
390 ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
391 return false;
394 if (!_bfd_elf_merge_object_attributes (ibfd, info))
395 return false;
397 /* If the input BFD is not a dynamic object and it does not contain any
398 non-data sections, do not account its ABI. For example, various
399 packages produces such data-only relocatable objects with
400 `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
401 But they are compatible with all ABIs. */
402 if (!(ibfd->flags & DYNAMIC))
404 asection *sec;
405 bool have_code_sections = false;
406 for (sec = ibfd->sections; sec != NULL; sec = sec->next)
407 if ((bfd_section_flags (sec)
408 & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
409 == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
411 have_code_sections = true;
412 break;
414 if (!have_code_sections)
415 return true;
418 if (!elf_flags_init (obfd))
420 elf_flags_init (obfd) = true;
421 elf_elfheader (obfd)->e_flags = in_flags;
422 return true;
424 else if (out_flags != in_flags)
426 if ((EF_LOONGARCH_IS_OBJ_V0 (out_flags)
427 && EF_LOONGARCH_IS_OBJ_V1 (in_flags))
428 || (EF_LOONGARCH_IS_OBJ_V0 (in_flags)
429 && EF_LOONGARCH_IS_OBJ_V1 (out_flags)))
431 elf_elfheader (obfd)->e_flags |= EF_LOONGARCH_OBJABI_V1;
432 out_flags = elf_elfheader (obfd)->e_flags;
433 in_flags = out_flags;
437 /* Disallow linking different ABIs. */
438 /* Only check relocation version.
439 The obj_v0 is compatible with obj_v1. */
440 if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
442 _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd);
443 goto fail;
446 return true;
448 fail:
449 bfd_set_error (bfd_error_bad_value);
450 return false;
453 /* Create the .got section. */
455 static bool
456 loongarch_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
458 flagword flags;
459 char *name;
460 asection *s, *s_got;
461 struct elf_link_hash_entry *h;
462 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
463 struct elf_link_hash_table *htab = elf_hash_table (info);
465 /* This function may be called more than once. */
466 if (htab->sgot != NULL)
467 return true;
469 flags = bed->dynamic_sec_flags;
470 name = bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got";
471 s = bfd_make_section_anyway_with_flags (abfd, name, flags | SEC_READONLY);
473 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
474 return false;
475 htab->srelgot = s;
477 s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
478 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
479 return false;
480 htab->sgot = s;
482 /* The first bit of the global offset table is the header. */
483 s->size += bed->got_header_size;
485 if (bed->want_got_plt)
487 s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
488 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
489 return false;
490 htab->sgotplt = s;
492 /* Reserve room for the header. */
493 s->size = GOTPLT_HEADER_SIZE;
496 if (bed->want_got_sym)
498 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
499 section. We don't do this in the linker script because we don't want
500 to define the symbol if we are not creating a global offset table. */
501 h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
502 "_GLOBAL_OFFSET_TABLE_");
503 elf_hash_table (info)->hgot = h;
504 if (h == NULL)
505 return false;
507 return true;
510 /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
511 .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
512 hash table. */
514 static bool
515 loongarch_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
517 struct loongarch_elf_link_hash_table *htab;
519 htab = loongarch_elf_hash_table (info);
520 BFD_ASSERT (htab != NULL);
522 if (!loongarch_elf_create_got_section (dynobj, info))
523 return false;
525 if (!_bfd_elf_create_dynamic_sections (dynobj, info))
526 return false;
528 if (!bfd_link_pic (info))
529 htab->sdyntdata
530 = bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
531 SEC_ALLOC | SEC_THREAD_LOCAL);
533 if (!htab->elf.splt || !htab->elf.srelplt || !htab->elf.sdynbss
534 || (!bfd_link_pic (info) && (!htab->elf.srelbss || !htab->sdyntdata)))
535 abort ();
537 return true;
540 static bool
541 loongarch_elf_record_tls_and_got_reference (bfd *abfd,
542 struct bfd_link_info *info,
543 struct elf_link_hash_entry *h,
544 unsigned long symndx,
545 char tls_type)
547 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
548 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
550 /* This is a global offset table entry for a local symbol. */
551 if (elf_local_got_refcounts (abfd) == NULL)
553 bfd_size_type size =
554 symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (tls_type));
555 if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
556 return false;
557 _bfd_loongarch_elf_local_got_tls_type (abfd) =
558 (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
561 switch (tls_type)
563 case GOT_NORMAL:
564 case GOT_TLS_GD:
565 case GOT_TLS_IE:
566 /* Need GOT. */
567 if (htab->elf.sgot == NULL
568 && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
569 return false;
570 if (h)
572 if (h->got.refcount < 0)
573 h->got.refcount = 0;
574 h->got.refcount++;
576 else
577 elf_local_got_refcounts (abfd)[symndx]++;
578 break;
579 case GOT_TLS_LE:
580 /* No need for GOT. */
581 break;
582 default:
583 _bfd_error_handler (_("Internal error: unreachable."));
584 return false;
587 char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
588 *new_tls_type |= tls_type;
589 if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
591 _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
592 "thread local symbol"),
593 abfd,
594 h ? h->root.root.string : "<local>");
595 return false;
598 return true;
601 /* Look through the relocs for a section during the first phase, and
602 allocate space in the global offset table or procedure linkage
603 table. */
605 static bool
606 loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
607 asection *sec, const Elf_Internal_Rela *relocs)
609 struct loongarch_elf_link_hash_table *htab;
610 Elf_Internal_Shdr *symtab_hdr;
611 struct elf_link_hash_entry **sym_hashes;
612 const Elf_Internal_Rela *rel;
613 asection *sreloc = NULL;
615 if (bfd_link_relocatable (info))
616 return true;
618 htab = loongarch_elf_hash_table (info);
619 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
620 sym_hashes = elf_sym_hashes (abfd);
622 if (htab->elf.dynobj == NULL)
623 htab->elf.dynobj = abfd;
625 for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
627 unsigned int r_type;
628 unsigned int r_symndx;
629 struct elf_link_hash_entry *h;
630 Elf_Internal_Sym *isym = NULL;
632 r_symndx = ELFNN_R_SYM (rel->r_info);
633 r_type = ELFNN_R_TYPE (rel->r_info);
635 if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
637 _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx);
638 return false;
641 if (r_symndx < symtab_hdr->sh_info)
643 /* A local symbol. */
644 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
645 if (isym == NULL)
646 return false;
648 if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
650 h = elfNN_loongarch_get_local_sym_hash (htab, abfd, rel, true);
651 if (h == NULL)
652 return false;
654 h->type = STT_GNU_IFUNC;
655 h->ref_regular = 1;
657 else
658 h = NULL;
660 else
662 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
663 while (h->root.type == bfd_link_hash_indirect
664 || h->root.type == bfd_link_hash_warning)
665 h = (struct elf_link_hash_entry *) h->root.u.i.link;
668 /* It is referenced by a non-shared object. */
669 if (h != NULL)
670 h->ref_regular = 1;
672 if (h && h->type == STT_GNU_IFUNC)
674 if (htab->elf.dynobj == NULL)
675 htab->elf.dynobj = abfd;
677 /* Create 'irelifunc' in PIC object. */
678 if (bfd_link_pic (info)
679 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
680 return false;
681 /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
682 else if (!htab->elf.splt
683 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
684 return false;
685 /* Create the ifunc sections, iplt and ipltgot, for static
686 executables. */
687 if ((r_type == R_LARCH_64 || r_type == R_LARCH_32)
688 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
689 return false;
691 if (h->plt.refcount < 0)
692 h->plt.refcount = 0;
693 h->plt.refcount++;
694 h->needs_plt = 1;
696 elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
699 int need_dynreloc = 0;
700 int only_need_pcrel = 0;
702 switch (r_type)
704 case R_LARCH_GOT_PC_HI20:
705 case R_LARCH_GOT_HI20:
706 case R_LARCH_SOP_PUSH_GPREL:
707 /* For la.global. */
708 if (h)
709 h->pointer_equality_needed = 1;
710 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
711 r_symndx,
712 GOT_NORMAL))
713 return false;
714 break;
716 case R_LARCH_TLS_LD_PC_HI20:
717 case R_LARCH_TLS_LD_HI20:
718 case R_LARCH_TLS_GD_PC_HI20:
719 case R_LARCH_TLS_GD_HI20:
720 case R_LARCH_SOP_PUSH_TLS_GD:
721 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
722 r_symndx,
723 GOT_TLS_GD))
724 return false;
725 break;
727 case R_LARCH_TLS_IE_PC_HI20:
728 case R_LARCH_TLS_IE_HI20:
729 case R_LARCH_SOP_PUSH_TLS_GOT:
730 if (bfd_link_pic (info))
731 /* May fail for lazy-bind. */
732 info->flags |= DF_STATIC_TLS;
734 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
735 r_symndx,
736 GOT_TLS_IE))
737 return false;
738 break;
740 case R_LARCH_TLS_LE_HI20:
741 case R_LARCH_SOP_PUSH_TLS_TPREL:
742 if (!bfd_link_executable (info))
743 return false;
745 info->flags |= DF_STATIC_TLS;
747 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
748 r_symndx,
749 GOT_TLS_LE))
750 return false;
751 break;
753 case R_LARCH_ABS_HI20:
754 case R_LARCH_SOP_PUSH_ABSOLUTE:
755 if (h != NULL)
756 /* If this reloc is in a read-only section, we might
757 need a copy reloc. We can't check reliably at this
758 stage whether the section is read-only, as input
759 sections have not yet been mapped to output sections.
760 Tentatively set the flag for now, and correct in
761 adjust_dynamic_symbol. */
762 h->non_got_ref = 1;
763 break;
765 case R_LARCH_PCALA_HI20:
766 if (h != NULL)
768 /* For pcalau12i + jirl. */
769 h->needs_plt = 1;
770 if (h->plt.refcount < 0)
771 h->plt.refcount = 0;
772 h->plt.refcount++;
774 h->non_got_ref = 1;
775 h->pointer_equality_needed = 1;
778 break;
780 case R_LARCH_B16:
781 case R_LARCH_B21:
782 case R_LARCH_B26:
783 if (h != NULL)
785 h->needs_plt = 1;
786 if (!bfd_link_pic (info))
787 h->non_got_ref = 1;
789 /* We try to create PLT stub for all non-local function. */
790 if (h->plt.refcount < 0)
791 h->plt.refcount = 0;
792 h->plt.refcount++;
795 break;
797 case R_LARCH_SOP_PUSH_PCREL:
798 if (h != NULL)
800 if (!bfd_link_pic (info))
801 h->non_got_ref = 1;
803 /* We try to create PLT stub for all non-local function. */
804 if (h->plt.refcount < 0)
805 h->plt.refcount = 0;
806 h->plt.refcount++;
807 h->pointer_equality_needed = 1;
810 break;
812 case R_LARCH_SOP_PUSH_PLT_PCREL:
813 /* This symbol requires a procedure linkage table entry. We
814 actually build the entry in adjust_dynamic_symbol,
815 because this might be a case of linking PIC code without
816 linking in any dynamic objects, in which case we don't
817 need to generate a procedure linkage table after all. */
818 if (h != NULL)
820 h->needs_plt = 1;
821 if (h->plt.refcount < 0)
822 h->plt.refcount = 0;
823 h->plt.refcount++;
825 break;
827 case R_LARCH_TLS_DTPREL32:
828 case R_LARCH_TLS_DTPREL64:
829 need_dynreloc = 1;
830 only_need_pcrel = 1;
831 break;
833 case R_LARCH_JUMP_SLOT:
834 case R_LARCH_32:
835 case R_LARCH_64:
837 need_dynreloc = 1;
839 /* If resolved symbol is defined in this object,
840 1. Under pie, the symbol is known. We convert it
841 into R_LARCH_RELATIVE and need load-addr still.
842 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
843 3. Under dll, R_LARCH_NN can't be changed normally, since
844 its defination could be covered by the one in executable.
845 For symbolic, we convert it into R_LARCH_RELATIVE.
846 Thus, only under pde, it needs pcrel only. We discard it. */
847 only_need_pcrel = bfd_link_pde (info);
849 if (h != NULL
850 && (!bfd_link_pic (info)
851 || h->type == STT_GNU_IFUNC))
853 /* This reloc might not bind locally. */
854 h->non_got_ref = 1;
855 h->pointer_equality_needed = 1;
857 if (!h->def_regular
858 || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
860 /* We may need a .plt entry if the symbol is a function
861 defined in a shared lib or is a function referenced
862 from the code or read-only section. */
863 h->plt.refcount += 1;
866 break;
868 case R_LARCH_GNU_VTINHERIT:
869 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
870 return false;
871 break;
873 case R_LARCH_GNU_VTENTRY:
874 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
875 return false;
876 break;
878 default:
879 break;
882 /* Record some info for sizing and allocating dynamic entry. */
883 if (need_dynreloc && (sec->flags & SEC_ALLOC))
885 /* When creating a shared object, we must copy these
886 relocs into the output file. We create a reloc
887 section in dynobj and make room for the reloc. */
888 struct elf_dyn_relocs *p;
889 struct elf_dyn_relocs **head;
891 if (sreloc == NULL)
893 sreloc
894 = _bfd_elf_make_dynamic_reloc_section (sec, htab->elf.dynobj,
895 LARCH_ELF_LOG_WORD_BYTES,
896 abfd, /*rela?*/ true);
897 if (sreloc == NULL)
898 return false;
901 /* If this is a global symbol, we count the number of
902 relocations we need for this symbol. */
903 if (h != NULL)
904 head = &h->dyn_relocs;
905 else
907 /* Track dynamic relocs needed for local syms too.
908 We really need local syms available to do this
909 easily. Oh well. */
911 asection *s;
912 void *vpp;
914 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
915 if (s == NULL)
916 s = sec;
918 vpp = &elf_section_data (s)->local_dynrel;
919 head = (struct elf_dyn_relocs **) vpp;
922 p = *head;
923 if (p == NULL || p->sec != sec)
925 bfd_size_type amt = sizeof *p;
926 p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt);
927 if (p == NULL)
928 return false;
929 p->next = *head;
930 *head = p;
931 p->sec = sec;
932 p->count = 0;
933 p->pc_count = 0;
936 p->count++;
937 p->pc_count += only_need_pcrel;
941 return true;
944 /* Find dynamic relocs for H that apply to read-only sections. */
946 static asection *
947 readonly_dynrelocs (struct elf_link_hash_entry *h)
949 struct elf_dyn_relocs *p;
951 for (p = h->dyn_relocs; p != NULL; p = p->next)
953 asection *s = p->sec->output_section;
955 if (s != NULL && (s->flags & SEC_READONLY) != 0)
956 return p->sec;
958 return NULL;
961 /* Adjust a symbol defined by a dynamic object and referenced by a
962 regular object. The current definition is in some section of the
963 dynamic object, but we're not including those sections. We have to
964 change the definition to something the rest of the link can
965 understand. */
966 static bool
967 loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
968 struct elf_link_hash_entry *h)
970 struct loongarch_elf_link_hash_table *htab;
971 bfd *dynobj;
973 htab = loongarch_elf_hash_table (info);
974 BFD_ASSERT (htab != NULL);
976 dynobj = htab->elf.dynobj;
978 /* Make sure we know what is going on here. */
979 BFD_ASSERT (dynobj != NULL
980 && (h->needs_plt
981 || h->type == STT_GNU_IFUNC
982 || h->is_weakalias
983 || (h->def_dynamic
984 && h->ref_regular
985 && !h->def_regular)));
987 /* If this is a function, put it in the procedure linkage table. We
988 will fill in the contents of the procedure linkage table later
989 (although we could actually do it here). */
990 if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
992 if (h->plt.refcount <= 0
993 || (h->type != STT_GNU_IFUNC
994 && (SYMBOL_REFERENCES_LOCAL (info, h)
995 || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
996 && h->root.type == bfd_link_hash_undefweak))))
998 /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
999 in an input file, but the symbol was never referred to by a
1000 dynamic object, or if all references were garbage collected.
1001 In such a case, we don't actually need to build a PLT entry. */
1002 h->plt.offset = MINUS_ONE;
1003 h->needs_plt = 0;
1006 return true;
1008 else
1009 h->plt.offset = MINUS_ONE;
1011 /* If this is a weak symbol, and there is a real definition, the
1012 processor independent code will have arranged for us to see the
1013 real definition first, and we can just use the same value. */
1014 if (h->is_weakalias)
1016 struct elf_link_hash_entry *def = weakdef (h);
1017 BFD_ASSERT (def->root.type == bfd_link_hash_defined);
1018 h->root.u.def.section = def->root.u.def.section;
1019 h->root.u.def.value = def->root.u.def.value;
1020 return true;
1023 /* R_LARCH_COPY is not adept glibc, not to generate. */
1024 /* Can not print anything, because make check ld. */
1025 return true;
1028 /* Allocate space in .plt, .got and associated reloc sections for
1029 dynamic relocs. */
1031 static bool
1032 allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1034 struct bfd_link_info *info;
1035 struct loongarch_elf_link_hash_table *htab;
1036 struct elf_dyn_relocs *p;
1038 if (h->root.type == bfd_link_hash_indirect)
1039 return true;
1041 if (h->type == STT_GNU_IFUNC
1042 && h->def_regular)
1043 return true;
1045 info = (struct bfd_link_info *) inf;
1046 htab = loongarch_elf_hash_table (info);
1047 bool dyn = htab->elf.dynamic_sections_created;
1048 BFD_ASSERT (htab != NULL);
1052 asection *plt, *gotplt, *relplt;
1054 if (!h->needs_plt)
1055 break;
1057 h->needs_plt = 0;
1059 if (htab->elf.splt)
1061 if (h->dynindx == -1 && !h->forced_local && dyn
1062 && h->root.type == bfd_link_hash_undefweak)
1064 if (!bfd_elf_link_record_dynamic_symbol (info, h))
1065 return false;
1068 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
1069 && h->type != STT_GNU_IFUNC)
1070 break;
1072 plt = htab->elf.splt;
1073 gotplt = htab->elf.sgotplt;
1074 relplt = htab->elf.srelplt;
1076 else if (htab->elf.iplt)
1078 /* .iplt only for IFUNC. */
1079 if (h->type != STT_GNU_IFUNC)
1080 break;
1082 plt = htab->elf.iplt;
1083 gotplt = htab->elf.igotplt;
1084 relplt = htab->elf.irelplt;
1086 else
1087 break;
1089 if (plt->size == 0)
1090 plt->size = PLT_HEADER_SIZE;
1092 h->plt.offset = plt->size;
1093 plt->size += PLT_ENTRY_SIZE;
1094 gotplt->size += GOT_ENTRY_SIZE;
1095 relplt->size += sizeof (ElfNN_External_Rela);
1097 /* If this symbol is not defined in a regular file, and we are
1098 not generating a shared library, then set the symbol to this
1099 location in the .plt. This is required to make function
1100 pointers compare as equal between the normal executable and
1101 the shared library. */
1102 if (!bfd_link_pic (info)
1103 && !h->def_regular)
1105 h->root.u.def.section = plt;
1106 h->root.u.def.value = h->plt.offset;
1109 h->needs_plt = 1;
1111 while (0);
1113 if (!h->needs_plt)
1114 h->plt.offset = MINUS_ONE;
1116 if (0 < h->got.refcount)
1118 asection *s;
1119 int tls_type = loongarch_elf_hash_entry (h)->tls_type;
1121 /* Make sure this symbol is output as a dynamic symbol.
1122 Undefined weak syms won't yet be marked as dynamic. */
1123 if (h->dynindx == -1 && !h->forced_local && dyn
1124 && h->root.type == bfd_link_hash_undefweak)
1126 if (!bfd_elf_link_record_dynamic_symbol (info, h))
1127 return false;
1130 s = htab->elf.sgot;
1131 h->got.offset = s->size;
1132 if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
1134 /* TLS_GD needs two dynamic relocs and two GOT slots. */
1135 if (tls_type & GOT_TLS_GD)
1137 s->size += 2 * GOT_ENTRY_SIZE;
1138 if (bfd_link_executable (info))
1140 /* Link exe and not defined local. */
1141 if (!SYMBOL_REFERENCES_LOCAL (info, h))
1142 htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1144 else
1146 if (SYMBOL_REFERENCES_LOCAL (info, h))
1147 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1148 else
1149 htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1153 /* TLS_IE needs one dynamic reloc and one GOT slot. */
1154 if (tls_type & GOT_TLS_IE)
1156 s->size += GOT_ENTRY_SIZE;
1158 if (bfd_link_executable (info))
1160 /* Link exe and not defined local. */
1161 if (!SYMBOL_REFERENCES_LOCAL (info, h))
1162 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1164 else
1166 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1170 else
1172 s->size += GOT_ENTRY_SIZE;
1173 if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1174 || h->root.type != bfd_link_hash_undefweak)
1175 && (bfd_link_pic (info)
1176 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
1178 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
1179 /* Undefined weak symbol in static PIE resolves to 0 without
1180 any dynamic relocations. */
1181 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1184 else
1185 h->got.offset = MINUS_ONE;
1187 if (h->dyn_relocs == NULL)
1188 return true;
1190 /* Extra dynamic relocate,
1191 * R_LARCH_64
1192 * R_LARCH_TLS_DTPRELNN
1193 * R_LARCH_JUMP_SLOT
1194 * R_LARCH_NN. */
1196 if (SYMBOL_CALLS_LOCAL (info, h))
1198 struct elf_dyn_relocs **pp;
1200 for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
1202 p->count -= p->pc_count;
1203 p->pc_count = 0;
1204 if (p->count == 0)
1205 *pp = p->next;
1206 else
1207 pp = &p->next;
1211 if (h->root.type == bfd_link_hash_undefweak)
1213 if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
1214 || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
1215 || (!bfd_link_pic (info) && h->non_got_ref))
1216 h->dyn_relocs = NULL;
1217 else if (h->dynindx == -1 && !h->forced_local)
1219 /* Make sure this symbol is output as a dynamic symbol.
1220 Undefined weak syms won't yet be marked as dynamic. */
1221 if (!bfd_elf_link_record_dynamic_symbol (info, h))
1222 return false;
1224 if (h->dynindx == -1)
1225 h->dyn_relocs = NULL;
1229 for (p = h->dyn_relocs; p != NULL; p = p->next)
1231 asection *sreloc = elf_section_data (p->sec)->sreloc;
1232 sreloc->size += p->count * sizeof (ElfNN_External_Rela);
1235 return true;
1238 /* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
1239 For local def and ref ifunc,
1240 dynamic relocations are stored in
1241 1. rela.srelgot section in dynamic object (dll or exec).
1242 2. rela.irelplt section in static executable.
1243 Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
1244 instead of rela.srelplt. Glibc ELF loader will not support
1245 R_LARCH_IRELATIVE relocation in rela.plt. */
1247 static bool
1248 local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
1249 struct elf_link_hash_entry *h,
1250 struct elf_dyn_relocs **head,
1251 unsigned int plt_entry_size,
1252 unsigned int plt_header_size,
1253 unsigned int got_entry_size,
1254 bool avoid_plt)
1256 asection *plt, *gotplt, *relplt;
1257 struct elf_dyn_relocs *p;
1258 unsigned int sizeof_reloc;
1259 const struct elf_backend_data *bed;
1260 struct elf_link_hash_table *htab;
1261 /* If AVOID_PLT is TRUE, don't use PLT if possible. */
1262 bool use_plt = !avoid_plt || h->plt.refcount > 0;
1263 bool need_dynreloc = !use_plt || bfd_link_pic (info);
1265 /* When a PIC object references a STT_GNU_IFUNC symbol defined
1266 in executable or it isn't referenced via PLT, the address of
1267 the resolved function may be used. But in non-PIC executable,
1268 the address of its plt slot may be used. Pointer equality may
1269 not work correctly. PIE or non-PLT reference should be used if
1270 pointer equality is required here.
1272 If STT_GNU_IFUNC symbol is defined in position-dependent executable,
1273 backend should change it to the normal function and set its address
1274 to its PLT entry which should be resolved by R_*_IRELATIVE at
1275 run-time. All external references should be resolved to its PLT in
1276 executable. */
1277 if (!need_dynreloc
1278 && !(bfd_link_pde (info) && h->def_regular)
1279 && (h->dynindx != -1
1280 || info->export_dynamic)
1281 && h->pointer_equality_needed)
1283 info->callbacks->einfo
1284 /* xgettext:c-format. */
1285 (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
1286 "equality in `%pB' can not be used when making an "
1287 "executable; recompile with -fPIE and relink with -pie\n"),
1288 h->root.root.string,
1289 h->root.u.def.section->owner);
1290 bfd_set_error (bfd_error_bad_value);
1291 return false;
1294 htab = elf_hash_table (info);
1296 /* When the symbol is marked with regular reference, if PLT isn't used
1297 or we are building a PIC object, we must keep dynamic relocation
1298 if there is non-GOT reference and use PLT if there is PC-relative
1299 reference. */
1300 if (need_dynreloc && h->ref_regular)
1302 bool keep = false;
1303 for (p = *head; p != NULL; p = p->next)
1304 if (p->count)
1306 h->non_got_ref = 1;
1307 /* Need dynamic relocations for non-GOT reference. */
1308 keep = true;
1309 if (p->pc_count)
1311 /* Must use PLT for PC-relative reference. */
1312 use_plt = true;
1313 need_dynreloc = bfd_link_pic (info);
1314 break;
1317 if (keep)
1318 goto keep;
1321 /* Support garbage collection against STT_GNU_IFUNC symbols. */
1322 if (h->plt.refcount <= 0 && h->got.refcount <= 0)
1324 h->got = htab->init_got_offset;
1325 h->plt = htab->init_plt_offset;
1326 *head = NULL;
1327 return true;
1330 /* Return and discard space for dynamic relocations against it if
1331 it is never referenced. */
1332 if (!h->ref_regular)
1334 if (h->plt.refcount > 0
1335 || h->got.refcount > 0)
1336 abort ();
1337 h->got = htab->init_got_offset;
1338 h->plt = htab->init_plt_offset;
1339 *head = NULL;
1340 return true;
1343 keep:
1344 bed = get_elf_backend_data (info->output_bfd);
1345 if (bed->rela_plts_and_copies_p)
1346 sizeof_reloc = bed->s->sizeof_rela;
1347 else
1348 sizeof_reloc = bed->s->sizeof_rel;
1350 /* When building a static executable, use iplt, igot.plt and
1351 rela.iplt sections for STT_GNU_IFUNC symbols. */
1352 if (htab->splt != NULL)
1354 plt = htab->splt;
1355 gotplt = htab->sgotplt;
1356 /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */
1357 relplt = htab->srelgot;
1359 /* If this is the first plt entry and PLT is used, make room for
1360 the special first entry. */
1361 if (plt->size == 0 && use_plt)
1362 plt->size += plt_header_size;
1364 else
1366 plt = htab->iplt;
1367 gotplt = htab->igotplt;
1368 relplt = htab->irelplt;
1371 if (use_plt)
1373 /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
1374 the original value for R_*_IRELATIVE. */
1375 h->plt.offset = plt->size;
1377 /* Make room for this entry in the plt/iplt section. */
1378 plt->size += plt_entry_size;
1380 /* We also need to make an entry in the got.plt/got.iplt section,
1381 which will be placed in the got section by the linker script. */
1382 gotplt->size += got_entry_size;
1385 /* We also need to make an entry in the rela.plt/.rela.iplt
1386 section for GOTPLT relocation if PLT is used. */
1387 if (use_plt)
1389 relplt->size += sizeof_reloc;
1390 relplt->reloc_count++;
1393 /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
1394 there is a non-GOT reference in a PIC object or PLT isn't used. */
1395 if (!need_dynreloc || !h->non_got_ref)
1396 *head = NULL;
1398 /* Finally, allocate space. */
1399 p = *head;
1400 if (p != NULL)
1402 bfd_size_type count = 0;
1405 count += p->count;
1406 p = p->next;
1408 while (p != NULL);
1410 htab->ifunc_resolvers = count != 0;
1412 /* Dynamic relocations are stored in
1413 1. rela.srelgot section in PIC object.
1414 2. rela.srelgot section in dynamic executable.
1415 3. rela.irelplt section in static executable. */
1416 if (htab->splt != NULL)
1417 htab->srelgot->size += count * sizeof_reloc;
1418 else
1420 relplt->size += count * sizeof_reloc;
1421 relplt->reloc_count += count;
1425 /* For STT_GNU_IFUNC symbol, got.plt has the real function address
1426 and got has the PLT entry adddress. We will load the GOT entry
1427 with the PLT entry in finish_dynamic_symbol if it is used. For
1428 branch, it uses got.plt. For symbol value, if PLT is used,
1429 1. Use got.plt in a PIC object if it is forced local or not
1430 dynamic.
1431 2. Use got.plt in a non-PIC object if pointer equality isn't
1432 needed.
1433 3. Use got.plt in PIE.
1434 4. Use got.plt if got isn't used.
1435 5. Otherwise use got so that it can be shared among different
1436 objects at run-time.
1437 If PLT isn't used, always use got for symbol value.
1438 We only need to relocate got entry in PIC object or in dynamic
1439 executable without PLT. */
1440 if (use_plt
1441 && (h->got.refcount <= 0
1442 || (bfd_link_pic (info)
1443 && (h->dynindx == -1
1444 || h->forced_local))
1445 || (
1446 !h->pointer_equality_needed)
1447 || htab->sgot == NULL))
1449 /* Use got.plt. */
1450 h->got.offset = (bfd_vma) -1;
1452 else
1454 if (!use_plt)
1456 /* PLT isn't used. */
1457 h->plt.offset = (bfd_vma) -1;
1459 if (h->got.refcount <= 0)
1461 /* GOT isn't need when there are only relocations for static
1462 pointers. */
1463 h->got.offset = (bfd_vma) -1;
1465 else
1467 h->got.offset = htab->sgot->size;
1468 htab->sgot->size += got_entry_size;
1469 /* Need to relocate the GOT entry in a PIC object or PLT isn't
1470 used. Otherwise, the GOT entry will be filled with the PLT
1471 entry and dynamic GOT relocation isn't needed. */
1472 if (need_dynreloc)
1474 /* For non-static executable, dynamic GOT relocation is in
1475 rela.got section, but for static executable, it is
1476 in rela.iplt section. */
1477 if (htab->splt != NULL)
1478 htab->srelgot->size += sizeof_reloc;
1479 else
1481 relplt->size += sizeof_reloc;
1482 relplt->reloc_count++;
1488 return true;
1491 /* Allocate space in .plt, .got and associated reloc sections for
1492 ifunc dynamic relocs. */
1494 static bool
1495 elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1497 struct bfd_link_info *info;
1498 /* An example of a bfd_link_hash_indirect symbol is versioned
1499 symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
1500 -> __gxx_personality_v0(bfd_link_hash_defined)
1502 There is no need to process bfd_link_hash_indirect symbols here
1503 because we will also be presented with the concrete instance of
1504 the symbol and loongarch_elf_copy_indirect_symbol () will have been
1505 called to copy all relevant data from the generic to the concrete
1506 symbol instance. */
1507 if (h->root.type == bfd_link_hash_indirect)
1508 return true;
1510 if (h->root.type == bfd_link_hash_warning)
1511 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1513 info = (struct bfd_link_info *) inf;
1515 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
1516 here if it is defined and referenced in a non-shared object. */
1517 if (h->type == STT_GNU_IFUNC && h->def_regular)
1519 if (SYMBOL_REFERENCES_LOCAL (info, h))
1520 return local_allocate_ifunc_dyn_relocs (info, h,
1521 &h->dyn_relocs,
1522 PLT_ENTRY_SIZE,
1523 PLT_HEADER_SIZE,
1524 GOT_ENTRY_SIZE,
1525 false);
1526 else
1527 return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
1528 &h->dyn_relocs,
1529 PLT_ENTRY_SIZE,
1530 PLT_HEADER_SIZE,
1531 GOT_ENTRY_SIZE,
1532 false);
1535 return true;
1538 /* Allocate space in .plt, .got and associated reloc sections for
1539 ifunc dynamic relocs. */
1541 static int
1542 elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
1544 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
1546 if (h->type != STT_GNU_IFUNC
1547 || !h->def_regular
1548 || !h->ref_regular
1549 || !h->forced_local
1550 || h->root.type != bfd_link_hash_defined)
1551 abort ();
1553 return elfNN_allocate_ifunc_dynrelocs (h, inf);
1556 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
1557 read-only sections. */
1559 static bool
1560 maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
1562 asection *sec;
1564 if (h->root.type == bfd_link_hash_indirect)
1565 return true;
1567 sec = readonly_dynrelocs (h);
1568 if (sec != NULL)
1570 struct bfd_link_info *info = (struct bfd_link_info *) info_p;
1572 info->flags |= DF_TEXTREL;
1573 info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' in "
1574 "read-only section `%pA'\n"),
1575 sec->owner, h->root.root.string, sec);
1577 /* Not an error, just cut short the traversal. */
1578 return false;
1580 return true;
1583 static bool
1584 loongarch_elf_size_dynamic_sections (bfd *output_bfd,
1585 struct bfd_link_info *info)
1587 struct loongarch_elf_link_hash_table *htab;
1588 bfd *dynobj;
1589 asection *s;
1590 bfd *ibfd;
1592 htab = loongarch_elf_hash_table (info);
1593 BFD_ASSERT (htab != NULL);
1594 dynobj = htab->elf.dynobj;
1595 BFD_ASSERT (dynobj != NULL);
1597 if (htab->elf.dynamic_sections_created)
1599 /* Set the contents of the .interp section to the interpreter. */
1600 if (bfd_link_executable (info) && !info->nointerp)
1602 const char *interpreter;
1603 s = bfd_get_linker_section (dynobj, ".interp");
1604 BFD_ASSERT (s != NULL);
1606 if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS32)
1607 interpreter = "/lib32/ld.so.1";
1608 else if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS64)
1609 interpreter = "/lib64/ld.so.1";
1610 else
1611 interpreter = "/lib/ld.so.1";
1613 s->contents = (unsigned char *) interpreter;
1614 s->size = strlen (interpreter) + 1;
1618 /* Set up .got offsets for local syms, and space for local dynamic
1619 relocs. */
1620 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
1622 bfd_signed_vma *local_got;
1623 bfd_signed_vma *end_local_got;
1624 char *local_tls_type;
1625 bfd_size_type locsymcount;
1626 Elf_Internal_Shdr *symtab_hdr;
1627 asection *srel;
1629 if (!is_loongarch_elf (ibfd))
1630 continue;
1632 for (s = ibfd->sections; s != NULL; s = s->next)
1634 struct elf_dyn_relocs *p;
1636 for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
1638 p->count -= p->pc_count;
1639 if (!bfd_is_abs_section (p->sec)
1640 && bfd_is_abs_section (p->sec->output_section))
1642 /* Input section has been discarded, either because
1643 it is a copy of a linkonce section or due to
1644 linker script /DISCARD/, so we'll be discarding
1645 the relocs too. */
1647 else if (0 < p->count)
1649 srel = elf_section_data (p->sec)->sreloc;
1650 srel->size += p->count * sizeof (ElfNN_External_Rela);
1651 if ((p->sec->output_section->flags & SEC_READONLY) != 0)
1652 info->flags |= DF_TEXTREL;
1657 local_got = elf_local_got_refcounts (ibfd);
1658 if (!local_got)
1659 continue;
1661 symtab_hdr = &elf_symtab_hdr (ibfd);
1662 locsymcount = symtab_hdr->sh_info;
1663 end_local_got = local_got + locsymcount;
1664 local_tls_type = _bfd_loongarch_elf_local_got_tls_type (ibfd);
1665 s = htab->elf.sgot;
1666 srel = htab->elf.srelgot;
1667 for (; local_got < end_local_got; ++local_got, ++local_tls_type)
1669 if (0 < *local_got)
1671 *local_got = s->size;
1673 /* TLS gd use two got. */
1674 if (*local_tls_type & GOT_TLS_GD)
1675 s->size += GOT_ENTRY_SIZE * 2;
1676 else
1677 /* Normal got, tls ie/ld use one got. */
1678 s->size += GOT_ENTRY_SIZE;
1680 if (bfd_link_executable (info)
1681 && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
1682 ;/* Do nothing. */
1683 else
1685 srel->size += sizeof (ElfNN_External_Rela);
1688 else
1689 *local_got = MINUS_ONE;
1693 /* Allocate global sym .plt and .got entries, and space for global
1694 sym dynamic relocs. */
1695 elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
1697 /* Allocate global ifunc sym .plt and .got entries, and space for global
1698 ifunc sym dynamic relocs. */
1699 elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info);
1701 /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1702 htab_traverse (htab->loc_hash_table,
1703 elfNN_allocate_local_ifunc_dynrelocs, info);
1705 /* Don't allocate .got.plt section if there are no PLT. */
1706 if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE
1707 && (htab->elf.splt == NULL || htab->elf.splt->size == 0))
1708 htab->elf.sgotplt->size = 0;
1710 /* The check_relocs and adjust_dynamic_symbol entry points have
1711 determined the sizes of the various dynamic sections. Allocate
1712 memory for them. */
1713 for (s = dynobj->sections; s != NULL; s = s->next)
1715 if ((s->flags & SEC_LINKER_CREATED) == 0)
1716 continue;
1718 if (s == htab->elf.splt || s == htab->elf.iplt || s == htab->elf.sgot
1719 || s == htab->elf.sgotplt || s == htab->elf.igotplt
1720 || s == htab->elf.sdynbss || s == htab->elf.sdynrelro)
1722 /* Strip this section if we don't need it; see the
1723 comment below. */
1725 else if (strncmp (s->name, ".rela", 5) == 0)
1727 if (s->size != 0)
1729 /* We use the reloc_count field as a counter if we need
1730 to copy relocs into the output file. */
1731 s->reloc_count = 0;
1734 else
1736 /* It's not one of our sections. */
1737 continue;
1740 if (s->size == 0)
1742 /* If we don't need this section, strip it from the
1743 output file. This is mostly to handle .rela.bss and
1744 .rela.plt. We must create both sections in
1745 create_dynamic_sections, because they must be created
1746 before the linker maps input sections to output
1747 sections. The linker does that before
1748 adjust_dynamic_symbol is called, and it is that
1749 function which decides whether anything needs to go
1750 into these sections. */
1751 s->flags |= SEC_EXCLUDE;
1752 continue;
1755 if ((s->flags & SEC_HAS_CONTENTS) == 0)
1756 continue;
1758 /* Allocate memory for the section contents. Zero the memory
1759 for the benefit of .rela.plt, which has 4 unused entries
1760 at the beginning, and we don't want garbage. */
1761 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
1762 if (s->contents == NULL)
1763 return false;
1766 if (elf_hash_table (info)->dynamic_sections_created)
1768 /* Add some entries to the .dynamic section. We fill in the
1769 values later, in loongarch_elf_finish_dynamic_sections, but we
1770 must add the entries now so that we get the correct size for
1771 the .dynamic section. The DT_DEBUG entry is filled in by the
1772 dynamic linker and used by the debugger. */
1773 #define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1775 if (bfd_link_executable (info))
1777 if (!add_dynamic_entry (DT_DEBUG, 0))
1778 return false;
1781 if (htab->elf.srelplt->size != 0)
1783 if (!add_dynamic_entry (DT_PLTGOT, 0)
1784 || !add_dynamic_entry (DT_PLTRELSZ, 0)
1785 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
1786 || !add_dynamic_entry (DT_JMPREL, 0))
1787 return false;
1790 if (!add_dynamic_entry (DT_RELA, 0)
1791 || !add_dynamic_entry (DT_RELASZ, 0)
1792 || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
1793 return false;
1795 /* If any dynamic relocs apply to a read-only section,
1796 then we need a DT_TEXTREL entry. */
1797 if ((info->flags & DF_TEXTREL) == 0)
1798 elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
1800 if (info->flags & DF_TEXTREL)
1802 if (!add_dynamic_entry (DT_TEXTREL, 0))
1803 return false;
1804 /* Clear the DF_TEXTREL flag. It will be set again if we
1805 write out an actual text relocation; we may not, because
1806 at this point we do not know whether e.g. any .eh_frame
1807 absolute relocations have been converted to PC-relative. */
1808 info->flags &= ~DF_TEXTREL;
1811 #undef add_dynamic_entry
1813 return true;
1816 #define LARCH_LD_STACK_DEPTH 16
1817 static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
1818 static size_t larch_stack_top = 0;
1820 static bfd_reloc_status_type
1821 loongarch_push (int64_t val)
1823 if (LARCH_LD_STACK_DEPTH <= larch_stack_top)
1824 return bfd_reloc_outofrange;
1825 larch_opc_stack[larch_stack_top++] = val;
1826 return bfd_reloc_ok;
1829 static bfd_reloc_status_type
1830 loongarch_pop (int64_t *val)
1832 if (larch_stack_top == 0)
1833 return bfd_reloc_outofrange;
1834 BFD_ASSERT (val);
1835 *val = larch_opc_stack[--larch_stack_top];
1836 return bfd_reloc_ok;
1839 static bfd_reloc_status_type
1840 loongarch_top (int64_t *val)
1842 if (larch_stack_top == 0)
1843 return bfd_reloc_outofrange;
1844 BFD_ASSERT (val);
1845 *val = larch_opc_stack[larch_stack_top - 1];
1846 return bfd_reloc_ok;
1849 static void
1850 loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
1852 BFD_ASSERT (s && s->contents);
1853 const struct elf_backend_data *bed;
1854 bfd_byte *loc;
1856 bed = get_elf_backend_data (abfd);
1857 if (!(s->size > s->reloc_count * bed->s->sizeof_rela))
1858 BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela);
1859 loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
1860 bed->s->swap_reloca_out (abfd, rel, loc);
1863 /* Check rel->r_offset in range of contents. */
1864 static bfd_reloc_status_type
1865 loongarch_check_offset (const Elf_Internal_Rela *rel,
1866 const asection *input_section)
1868 if (0 == strcmp(input_section->name, ".text")
1869 && rel->r_offset > input_section->size)
1870 return bfd_reloc_overflow;
1872 return bfd_reloc_ok;
1875 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1876 ({ \
1877 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1878 if (ret == bfd_reloc_ok) \
1880 ret = loongarch_pop (&op1); \
1881 if (ret == bfd_reloc_ok) \
1882 ret = loongarch_push (op3); \
1884 ret; \
1887 static bfd_reloc_status_type
1888 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
1889 const asection *input_section ATTRIBUTE_UNUSED,
1890 reloc_howto_type *howto, bfd *input_bfd,
1891 bfd_byte *contents, bfd_vma reloc_val)
1893 int bits = bfd_get_reloc_size (howto) * 8;
1894 uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
1896 if (!loongarch_adjust_reloc_bitsfield (input_bfd, howto, &reloc_val))
1897 return bfd_reloc_overflow;
1899 insn = (insn & (uint32_t)howto->src_mask)
1900 | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val);
1902 bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
1904 return bfd_reloc_ok;
1907 static bfd_reloc_status_type
1908 perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
1909 reloc_howto_type *howto, bfd_vma value,
1910 bfd *input_bfd, bfd_byte *contents)
1912 int64_t opr1, opr2, opr3;
1913 bfd_reloc_status_type r = bfd_reloc_ok;
1914 int bits = bfd_get_reloc_size (howto) * 8;
1916 switch (ELFNN_R_TYPE (rel->r_info))
1918 case R_LARCH_SOP_PUSH_PCREL:
1919 case R_LARCH_SOP_PUSH_ABSOLUTE:
1920 case R_LARCH_SOP_PUSH_GPREL:
1921 case R_LARCH_SOP_PUSH_TLS_TPREL:
1922 case R_LARCH_SOP_PUSH_TLS_GOT:
1923 case R_LARCH_SOP_PUSH_TLS_GD:
1924 case R_LARCH_SOP_PUSH_PLT_PCREL:
1925 r = loongarch_push (value);
1926 break;
1928 case R_LARCH_SOP_PUSH_DUP:
1929 r = loongarch_pop (&opr1);
1930 if (r == bfd_reloc_ok)
1932 r = loongarch_push (opr1);
1933 if (r == bfd_reloc_ok)
1934 r = loongarch_push (opr1);
1936 break;
1938 case R_LARCH_SOP_ASSERT:
1939 r = loongarch_pop (&opr1);
1940 if (r != bfd_reloc_ok || !opr1)
1941 r = bfd_reloc_notsupported;
1942 break;
1944 case R_LARCH_SOP_NOT:
1945 r = loongarch_pop (&opr1);
1946 if (r == bfd_reloc_ok)
1947 r = loongarch_push (!opr1);
1948 break;
1950 case R_LARCH_SOP_SUB:
1951 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
1952 break;
1954 case R_LARCH_SOP_SL:
1955 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
1956 break;
1958 case R_LARCH_SOP_SR:
1959 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
1960 break;
1962 case R_LARCH_SOP_AND:
1963 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
1964 break;
1966 case R_LARCH_SOP_ADD:
1967 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
1968 break;
1970 case R_LARCH_SOP_IF_ELSE:
1971 r = loongarch_pop (&opr3);
1972 if (r == bfd_reloc_ok)
1974 r = loongarch_pop (&opr2);
1975 if (r == bfd_reloc_ok)
1977 r = loongarch_pop (&opr1);
1978 if (r == bfd_reloc_ok)
1979 r = loongarch_push (opr1 ? opr2 : opr3);
1982 break;
1984 case R_LARCH_SOP_POP_32_S_10_5:
1985 case R_LARCH_SOP_POP_32_S_10_12:
1986 case R_LARCH_SOP_POP_32_S_10_16:
1987 case R_LARCH_SOP_POP_32_S_10_16_S2:
1988 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1989 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1990 case R_LARCH_SOP_POP_32_S_5_20:
1991 case R_LARCH_SOP_POP_32_U_10_12:
1992 case R_LARCH_SOP_POP_32_U:
1993 r = loongarch_pop (&opr1);
1994 if (r != bfd_reloc_ok)
1995 break;
1996 r = loongarch_check_offset (rel, input_section);
1997 if (r != bfd_reloc_ok)
1998 break;
2000 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
2001 howto, input_bfd,
2002 contents, (bfd_vma)opr1);
2003 break;
2005 case R_LARCH_TLS_DTPREL32:
2006 case R_LARCH_32:
2007 case R_LARCH_TLS_DTPREL64:
2008 case R_LARCH_64:
2009 r = loongarch_check_offset (rel, input_section);
2010 if (r != bfd_reloc_ok)
2011 break;
2013 bfd_put (bits, input_bfd, value, contents + rel->r_offset);
2014 break;
2016 /* LoongArch only has add/sub reloc pair, not has set/sub reloc pair.
2017 Because set/sub reloc pair not support multi-thread. While add/sub
2018 reloc pair process order not affect the final result.
2020 For add/sub reloc, the original value will be involved in the
2021 calculation. In order not to add/sub extra value, we write 0 to symbol
2022 address at assembly time.
2024 add/sub reloc bits determined by the value after symbol subtraction,
2025 not symbol value.
2027 add/sub reloc save part of the symbol value, so we only need to
2028 save howto->dst_mask bits. */
2029 case R_LARCH_ADD6:
2030 case R_LARCH_SUB6:
2032 bfd_vma word = bfd_get (howto->bitsize, input_bfd,
2033 contents + rel->r_offset);
2034 word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
2035 bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
2036 r = bfd_reloc_ok;
2037 break;
2040 /* Not need to read the original value, just write the new value. */
2041 case R_LARCH_ADD8:
2042 case R_LARCH_ADD16:
2043 case R_LARCH_ADD24:
2044 case R_LARCH_ADD32:
2045 case R_LARCH_ADD64:
2046 case R_LARCH_SUB8:
2047 case R_LARCH_SUB16:
2048 case R_LARCH_SUB24:
2049 case R_LARCH_SUB32:
2050 case R_LARCH_SUB64:
2052 /* Because add/sub reloc is processed separately,
2053 so the high bits is invalid. */
2054 bfd_vma word = value & howto->dst_mask;
2055 bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
2056 r = bfd_reloc_ok;
2057 break;
2060 case R_LARCH_ADD_ULEB128:
2061 case R_LARCH_SUB_ULEB128:
2063 unsigned int len = 0;
2064 /* Before write uleb128, first read it to get it's length. */
2065 _bfd_read_unsigned_leb128 (input_bfd, contents + rel->r_offset, &len);
2066 loongarch_write_unsigned_leb128 (contents + rel->r_offset, len, value);
2067 r = bfd_reloc_ok;
2068 break;
2071 /* For eh_frame and debug info. */
2072 case R_LARCH_32_PCREL:
2073 case R_LARCH_64_PCREL:
2075 value -= sec_addr (input_section) + rel->r_offset;
2076 value += rel->r_addend;
2077 bfd_vma word = bfd_get (howto->bitsize, input_bfd,
2078 contents + rel->r_offset);
2079 word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
2080 bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
2081 r = bfd_reloc_ok;
2082 break;
2085 /* New reloc type.
2086 R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */
2087 case R_LARCH_B16:
2088 case R_LARCH_B21:
2089 case R_LARCH_B26:
2090 case R_LARCH_ABS_HI20:
2091 case R_LARCH_ABS_LO12:
2092 case R_LARCH_ABS64_LO20:
2093 case R_LARCH_ABS64_HI12:
2094 case R_LARCH_PCALA_HI20:
2095 case R_LARCH_PCALA_LO12:
2096 case R_LARCH_PCALA64_LO20:
2097 case R_LARCH_PCALA64_HI12:
2098 case R_LARCH_GOT_PC_HI20:
2099 case R_LARCH_GOT_PC_LO12:
2100 case R_LARCH_GOT64_PC_LO20:
2101 case R_LARCH_GOT64_PC_HI12:
2102 case R_LARCH_GOT_HI20:
2103 case R_LARCH_GOT_LO12:
2104 case R_LARCH_GOT64_LO20:
2105 case R_LARCH_GOT64_HI12:
2106 case R_LARCH_TLS_LE_HI20:
2107 case R_LARCH_TLS_LE_LO12:
2108 case R_LARCH_TLS_LE64_LO20:
2109 case R_LARCH_TLS_LE64_HI12:
2110 case R_LARCH_TLS_IE_PC_HI20:
2111 case R_LARCH_TLS_IE_PC_LO12:
2112 case R_LARCH_TLS_IE64_PC_LO20:
2113 case R_LARCH_TLS_IE64_PC_HI12:
2114 case R_LARCH_TLS_IE_HI20:
2115 case R_LARCH_TLS_IE_LO12:
2116 case R_LARCH_TLS_IE64_LO20:
2117 case R_LARCH_TLS_IE64_HI12:
2118 case R_LARCH_TLS_LD_PC_HI20:
2119 case R_LARCH_TLS_LD_HI20:
2120 case R_LARCH_TLS_GD_PC_HI20:
2121 case R_LARCH_TLS_GD_HI20:
2122 case R_LARCH_PCREL20_S2:
2123 r = loongarch_check_offset (rel, input_section);
2124 if (r != bfd_reloc_ok)
2125 break;
2127 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
2128 howto, input_bfd,
2129 contents, value);
2130 break;
2132 case R_LARCH_RELAX:
2133 break;
2135 default:
2136 r = bfd_reloc_notsupported;
2138 return r;
2141 #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
2142 static struct
2144 bfd *bfd;
2145 asection *section;
2146 bfd_vma r_offset;
2147 int r_type;
2148 bfd_vma relocation;
2149 Elf_Internal_Sym *sym;
2150 struct elf_link_hash_entry *h;
2151 bfd_vma addend;
2152 int64_t top_then;
2153 } larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
2154 static size_t larch_reloc_queue_head = 0;
2155 static size_t larch_reloc_queue_tail = 0;
2157 static const char *
2158 loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
2159 Elf_Internal_Sym *sym)
2161 const char *ret = NULL;
2162 if (sym)
2163 ret = bfd_elf_string_from_elf_section (input_bfd,
2164 elf_symtab_hdr (input_bfd).sh_link,
2165 sym->st_name);
2166 else if (h)
2167 ret = h->root.root.string;
2169 if (ret == NULL || *ret == '\0')
2170 ret = "<nameless>";
2171 return ret;
2174 static void
2175 loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
2176 bfd_vma r_offset, Elf_Internal_Sym *sym,
2177 struct elf_link_hash_entry *h, bfd_vma addend)
2179 if ((larch_reloc_queue_head == 0
2180 && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
2181 || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
2182 larch_reloc_queue_head =
2183 (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2184 larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
2185 larch_reloc_queue[larch_reloc_queue_tail].section = section;
2186 larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
2187 larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
2188 larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
2189 larch_reloc_queue[larch_reloc_queue_tail].h = h;
2190 larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
2191 loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
2192 larch_reloc_queue_tail =
2193 (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2196 static void
2197 loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
2199 size_t i = larch_reloc_queue_head;
2200 bfd *a_bfd = NULL;
2201 asection *section = NULL;
2202 bfd_vma r_offset = 0;
2203 int inited = 0;
2204 p ("Dump relocate record:\n");
2205 p ("stack top\t\trelocation name\t\tsymbol");
2206 while (i != larch_reloc_queue_tail)
2208 if (a_bfd != larch_reloc_queue[i].bfd
2209 || section != larch_reloc_queue[i].section
2210 || r_offset != larch_reloc_queue[i].r_offset)
2212 a_bfd = larch_reloc_queue[i].bfd;
2213 section = larch_reloc_queue[i].section;
2214 r_offset = larch_reloc_queue[i].r_offset;
2215 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
2216 larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
2219 if (!inited)
2220 inited = 1, p ("...\n");
2222 reloc_howto_type *howto =
2223 loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
2224 larch_reloc_queue[i].r_type);
2225 p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
2226 howto ? howto->name : "<unknown reloc>",
2227 loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
2228 larch_reloc_queue[i].sym));
2230 long addend = larch_reloc_queue[i].addend;
2231 if (addend < 0)
2232 p (" - %ld", -addend);
2233 else if (0 < addend)
2234 p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
2236 p ("\n");
2237 i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2239 p ("\n"
2240 "-- Record dump end --\n\n");
2243 static bool
2244 loongarch_reloc_is_fatal (struct bfd_link_info *info,
2245 bfd *input_bfd,
2246 asection *input_section,
2247 Elf_Internal_Rela *rel,
2248 reloc_howto_type *howto,
2249 bfd_reloc_status_type rtype,
2250 bool is_undefweak,
2251 const char *name,
2252 const char *msg)
2254 bool fatal = true;
2255 switch (rtype)
2257 /* 'dangerous' means we do it but can't promise it's ok
2258 'unsupport' means out of ability of relocation type
2259 'undefined' means we can't deal with the undefined symbol. */
2260 case bfd_reloc_undefined:
2261 info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
2262 rel->r_offset, true);
2263 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2264 input_bfd, input_section, rel->r_offset,
2265 howto->name,
2266 is_undefweak ? "[undefweak] " : "", name, msg);
2267 break;
2268 case bfd_reloc_dangerous:
2269 info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
2270 input_bfd, input_section, rel->r_offset,
2271 howto->name,
2272 is_undefweak ? "[undefweak] " : "", name, msg);
2273 fatal = false;
2274 break;
2275 case bfd_reloc_notsupported:
2276 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2277 input_bfd, input_section, rel->r_offset,
2278 howto->name,
2279 is_undefweak ? "[undefweak] " : "", name, msg);
2280 break;
2281 default:
2282 break;
2284 return fatal;
2287 /* If lo12 immediate > 0x7ff, because sign-extend caused by addi.d/ld.d,
2288 hi20 immediate need to add 0x1.
2289 For example: pc 0x120000000, symbol 0x120000812
2290 lo12 immediate is 0x812, 0x120000812 & 0xfff = 0x812
2291 hi20 immediate is 1, because lo12 imm > 0x7ff, symbol need to add 0x1000
2292 (((0x120000812 + 0x1000) & ~0xfff) - (0x120000000 & ~0xfff)) >> 12 = 0x1
2294 At run:
2295 pcalau12i $t0, hi20 (0x1)
2296 $t0 = 0x120000000 + (0x1 << 12) = 0x120001000
2297 addi.d $t0, $t0, lo12 (0x812)
2298 $t0 = 0x120001000 + 0xfffffffffffff812 (-(0x1000 - 0x812) = -0x7ee)
2299 = 0x120001000 - 0x7ee (0x1000 - 0x7ee = 0x812)
2300 = 0x120000812
2301 Without hi20 add 0x1000, the result 0x120000000 - 0x7ee = 0x11ffff812 is
2302 error.
2303 0x1000 + sign-extend-to64(0x8xx) = 0x8xx. */
2304 #define RELOCATE_CALC_PC32_HI20(relocation, pc) \
2305 ({ \
2306 bfd_vma __lo = (relocation) & ((bfd_vma)0xfff); \
2307 relocation = (relocation & ~(bfd_vma)0xfff) \
2308 - (pc & ~(bfd_vma)0xfff); \
2309 if (__lo > 0x7ff) \
2310 relocation += 0x1000; \
2313 /* For example: pc is 0x11000010000100, symbol is 0x1812348ffff812
2314 offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff)
2315 = 0x712347ffff000
2316 lo12: 0x1812348ffff812 & 0xfff = 0x812
2317 hi20: 0x7ffff + 0x1(lo12 > 0x7ff) = 0x80000
2318 lo20: 0x71234 - 0x1(lo12 > 0x7ff) + 0x1(hi20 > 0x7ffff)
2319 hi12: 0x0
2321 pcalau12i $t1, hi20 (0x80000)
2322 $t1 = 0x11000010000100 + sign-extend(0x80000 << 12)
2323 = 0x11000010000100 + 0xffffffff80000000
2324 = 0x10ffff90000000
2325 addi.d $t0, $zero, lo12 (0x812)
2326 $t0 = 0xfffffffffffff812 (if lo12 > 0x7ff, because sign-extend,
2327 lo20 need to sub 0x1)
2328 lu32i.d $t0, lo20 (0x71234)
2329 $t0 = {0x71234, 0xfffff812}
2330 = 0x71234fffff812
2331 lu52i.d $t0, hi12 (0x0)
2332 $t0 = {0x0, 0x71234fffff812}
2333 = 0x71234fffff812
2334 add.d $t1, $t1, $t0
2335 $t1 = 0x10ffff90000000 + 0x71234fffff812
2336 = 0x1812348ffff812. */
2337 #define RELOCATE_CALC_PC64_HI32(relocation, pc) \
2338 ({ \
2339 bfd_vma __lo = (relocation & (bfd_vma)0xfff); \
2340 relocation = (relocation & ~(bfd_vma)0xfff) \
2341 - (pc & ~(bfd_vma)0xfff); \
2342 if (__lo > 0x7ff) \
2343 relocation += (0x1000 - 0x100000000); \
2344 if (relocation & 0x80000000) \
2345 relocation += 0x100000000; \
2348 static int
2349 loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
2350 bfd *input_bfd, asection *input_section,
2351 bfd_byte *contents, Elf_Internal_Rela *relocs,
2352 Elf_Internal_Sym *local_syms,
2353 asection **local_sections)
2355 Elf_Internal_Rela *rel;
2356 Elf_Internal_Rela *relend;
2357 bool fatal = false;
2358 asection *sreloc = elf_section_data (input_section)->sreloc;
2359 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2360 Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
2361 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
2362 bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
2363 bool is_pic = bfd_link_pic (info);
2364 bool is_dyn = elf_hash_table (info)->dynamic_sections_created;
2365 asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
2366 asection *got = htab->elf.sgot;
2368 relend = relocs + input_section->reloc_count;
2369 for (rel = relocs; rel < relend; rel++)
2371 int r_type = ELFNN_R_TYPE (rel->r_info);
2372 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
2373 bfd_vma pc = sec_addr (input_section) + rel->r_offset;
2374 reloc_howto_type *howto = NULL;
2375 asection *sec = NULL;
2376 Elf_Internal_Sym *sym = NULL;
2377 struct elf_link_hash_entry *h = NULL;
2378 const char *name;
2379 bfd_reloc_status_type r = bfd_reloc_ok;
2380 bool is_ie, is_undefweak, unresolved_reloc, defined_local;
2381 bool resolved_local, resolved_dynly, resolved_to_const;
2382 char tls_type;
2383 bfd_vma relocation, off, ie_off;
2384 int i, j;
2386 howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
2387 if (howto == NULL || r_type == R_LARCH_GNU_VTINHERIT
2388 || r_type == R_LARCH_GNU_VTENTRY)
2389 continue;
2391 /* This is a final link. */
2392 if (r_symndx < symtab_hdr->sh_info)
2394 is_undefweak = false;
2395 unresolved_reloc = false;
2396 sym = local_syms + r_symndx;
2397 sec = local_sections[r_symndx];
2398 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
2400 /* Relocate against local STT_GNU_IFUNC symbol. */
2401 if (!bfd_link_relocatable (info)
2402 && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
2404 h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
2405 false);
2406 if (h == NULL)
2407 abort ();
2409 /* Set STT_GNU_IFUNC symbol value. */
2410 h->root.u.def.value = sym->st_value;
2411 h->root.u.def.section = sec;
2413 defined_local = true;
2414 resolved_local = true;
2415 resolved_dynly = false;
2416 resolved_to_const = false;
2418 /* Calc in funtion elf_link_input_bfd,
2419 * if #define elf_backend_rela_normal to 1. */
2420 if (bfd_link_relocatable (info)
2421 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
2422 continue;
2424 else
2426 bool warned, ignored;
2428 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
2429 r_symndx, symtab_hdr, sym_hashes,
2430 h, sec, relocation,
2431 unresolved_reloc, warned, ignored);
2432 /* Here means symbol isn't local symbol only and 'h != NULL'. */
2434 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
2435 symbol. And 'dynamic_undefined_weak' specify what to do when
2436 meeting undefweak. */
2438 if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
2440 defined_local = false;
2441 resolved_local = false;
2442 resolved_to_const = (!is_dyn || h->dynindx == -1
2443 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
2444 resolved_dynly = !resolved_local && !resolved_to_const;
2446 else if (warned)
2448 /* Symbol undefined offen means failed already. I don't know why
2449 'warned' here but I guess it want to continue relocating as if
2450 no error occures to find other errors as more as possible. */
2452 /* To avoid generating warning messages about truncated
2453 relocations, set the relocation's address to be the same as
2454 the start of this section. */
2455 relocation = (input_section->output_section
2456 ? input_section->output_section->vma
2457 : 0);
2459 defined_local = relocation != 0;
2460 resolved_local = defined_local;
2461 resolved_to_const = !resolved_local;
2462 resolved_dynly = false;
2464 else
2466 defined_local = !unresolved_reloc && !ignored;
2467 resolved_local =
2468 defined_local && SYMBOL_REFERENCES_LOCAL (info, h);
2469 resolved_dynly = !resolved_local;
2470 resolved_to_const = !resolved_local && !resolved_dynly;
2474 name = loongarch_sym_name (input_bfd, h, sym);
2476 if (sec != NULL && discarded_section (sec))
2477 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
2478 1, relend, howto, 0, contents);
2480 if (bfd_link_relocatable (info))
2481 continue;
2483 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2484 from removed linkonce sections, or sections discarded by a linker
2485 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2486 if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
2488 defined_local = false;
2489 resolved_local = false;
2490 resolved_dynly = false;
2491 resolved_to_const = true;
2494 /* The ifunc reference generate plt. */
2495 if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE)
2497 defined_local = true;
2498 resolved_local = true;
2499 resolved_dynly = false;
2500 resolved_to_const = false;
2501 relocation = sec_addr (plt) + h->plt.offset;
2504 unresolved_reloc = resolved_dynly;
2506 BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
2508 /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));. */
2510 BFD_ASSERT (!resolved_local || defined_local);
2512 is_ie = false;
2513 switch (r_type)
2515 case R_LARCH_MARK_PCREL:
2516 case R_LARCH_MARK_LA:
2517 case R_LARCH_NONE:
2518 r = bfd_reloc_continue;
2519 unresolved_reloc = false;
2520 break;
2522 case R_LARCH_32:
2523 case R_LARCH_64:
2524 if (resolved_dynly || (is_pic && resolved_local))
2526 Elf_Internal_Rela outrel;
2528 /* When generating a shared object, these relocations are copied
2529 into the output file to be resolved at run time. */
2531 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2532 input_section,
2533 rel->r_offset);
2535 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2536 && (input_section->flags & SEC_ALLOC));
2538 outrel.r_offset += sec_addr (input_section);
2540 /* A pointer point to a ifunc symbol. */
2541 if (h && h->type == STT_GNU_IFUNC)
2543 if (h->dynindx == -1)
2545 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2546 outrel.r_addend = (h->root.u.def.value
2547 + h->root.u.def.section->output_section->vma
2548 + h->root.u.def.section->output_offset);
2550 else
2552 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
2553 outrel.r_addend = 0;
2556 if (SYMBOL_REFERENCES_LOCAL (info, h))
2559 if (htab->elf.splt != NULL)
2560 sreloc = htab->elf.srelgot;
2561 else
2562 sreloc = htab->elf.irelplt;
2564 else
2567 if (bfd_link_pic (info))
2568 sreloc = htab->elf.irelifunc;
2569 else if (htab->elf.splt != NULL)
2570 sreloc = htab->elf.srelgot;
2571 else
2572 sreloc = htab->elf.irelplt;
2575 else if (resolved_dynly)
2577 if (h->dynindx == -1)
2579 if (h->root.type == bfd_link_hash_undefined)
2580 (*info->callbacks->undefined_symbol)
2581 (info, name, input_bfd, input_section,
2582 rel->r_offset, true);
2584 outrel.r_info = ELFNN_R_INFO (0, r_type);
2586 else
2587 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2589 outrel.r_addend = rel->r_addend;
2591 else
2593 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2594 outrel.r_addend = relocation + rel->r_addend;
2597 /* No alloc space of func allocate_dynrelocs. */
2598 if (unresolved_reloc
2599 && !(h && (h->is_weakalias || !h->dyn_relocs)))
2600 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2603 relocation += rel->r_addend;
2604 break;
2606 case R_LARCH_ADD6:
2607 case R_LARCH_ADD8:
2608 case R_LARCH_ADD16:
2609 case R_LARCH_ADD24:
2610 case R_LARCH_ADD32:
2611 case R_LARCH_ADD64:
2613 bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
2614 contents + rel->r_offset);
2615 relocation = old_value + relocation + rel->r_addend;
2616 break;
2619 case R_LARCH_SUB6:
2620 case R_LARCH_SUB8:
2621 case R_LARCH_SUB16:
2622 case R_LARCH_SUB24:
2623 case R_LARCH_SUB32:
2624 case R_LARCH_SUB64:
2626 bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
2627 contents + rel->r_offset);
2628 relocation = old_value - relocation - rel->r_addend;
2629 break;
2632 case R_LARCH_ADD_ULEB128:
2633 case R_LARCH_SUB_ULEB128:
2635 /* Get the value and length of the uleb128 data. */
2636 unsigned int len = 0;
2637 bfd_vma old_value = _bfd_read_unsigned_leb128 (input_bfd,
2638 contents + rel->r_offset, &len);
2640 if (R_LARCH_ADD_ULEB128 == ELFNN_R_TYPE (rel->r_info))
2641 relocation = old_value + relocation + rel->r_addend;
2642 else if (R_LARCH_SUB_ULEB128 == ELFNN_R_TYPE (rel->r_info))
2643 relocation = old_value - relocation - rel->r_addend;
2645 bfd_vma mask = (1 << (7 * len)) - 1;
2646 relocation &= mask;
2647 break;
2650 case R_LARCH_TLS_DTPREL32:
2651 case R_LARCH_TLS_DTPREL64:
2652 if (resolved_dynly)
2654 Elf_Internal_Rela outrel;
2656 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2657 input_section,
2658 rel->r_offset);
2659 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2660 && (input_section->flags & SEC_ALLOC));
2661 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2662 outrel.r_offset += sec_addr (input_section);
2663 outrel.r_addend = rel->r_addend;
2664 if (unresolved_reloc)
2665 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2666 break;
2669 if (resolved_to_const)
2670 fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
2671 rel, howto,
2672 bfd_reloc_notsupported,
2673 is_undefweak, name,
2674 "Internal:");
2675 if (resolved_local)
2677 if (!elf_hash_table (info)->tls_sec)
2679 fatal = loongarch_reloc_is_fatal (info, input_bfd,
2680 input_section, rel, howto, bfd_reloc_notsupported,
2681 is_undefweak, name, "TLS section not be created");
2683 else
2684 relocation -= elf_hash_table (info)->tls_sec->vma;
2686 else
2688 fatal = loongarch_reloc_is_fatal (info, input_bfd,
2689 input_section, rel, howto, bfd_reloc_undefined,
2690 is_undefweak, name,
2691 "TLS LE just can be resolved local only.");
2694 break;
2696 case R_LARCH_SOP_PUSH_TLS_TPREL:
2697 if (resolved_local)
2699 if (!elf_hash_table (info)->tls_sec)
2700 fatal = (loongarch_reloc_is_fatal
2701 (info, input_bfd, input_section, rel, howto,
2702 bfd_reloc_notsupported, is_undefweak, name,
2703 "TLS section not be created"));
2704 else
2705 relocation -= elf_hash_table (info)->tls_sec->vma;
2707 else
2708 fatal = (loongarch_reloc_is_fatal
2709 (info, input_bfd, input_section, rel, howto,
2710 bfd_reloc_undefined, is_undefweak, name,
2711 "TLS LE just can be resolved local only."));
2712 break;
2714 case R_LARCH_SOP_PUSH_ABSOLUTE:
2715 if (is_undefweak)
2717 if (resolved_dynly)
2718 fatal = (loongarch_reloc_is_fatal
2719 (info, input_bfd, input_section, rel, howto,
2720 bfd_reloc_dangerous, is_undefweak, name,
2721 "Someone require us to resolve undefweak "
2722 "symbol dynamically. \n"
2723 "But this reloc can't be done. "
2724 "I think I can't throw error "
2725 "for this\n"
2726 "so I resolved it to 0. "
2727 "I suggest to re-compile with '-fpic'."));
2729 relocation = 0;
2730 unresolved_reloc = false;
2731 break;
2734 if (resolved_to_const)
2736 relocation += rel->r_addend;
2737 break;
2740 if (is_pic)
2742 fatal = (loongarch_reloc_is_fatal
2743 (info, input_bfd, input_section, rel, howto,
2744 bfd_reloc_notsupported, is_undefweak, name,
2745 "Under PIC we don't know load address. Re-compile "
2746 "with '-fpic'?"));
2747 break;
2750 if (resolved_dynly)
2752 if (!(plt && h && h->plt.offset != MINUS_ONE))
2754 fatal = (loongarch_reloc_is_fatal
2755 (info, input_bfd, input_section, rel, howto,
2756 bfd_reloc_undefined, is_undefweak, name,
2757 "Can't be resolved dynamically. Try to re-compile "
2758 "with '-fpic'?"));
2759 break;
2762 if (rel->r_addend != 0)
2764 fatal = (loongarch_reloc_is_fatal
2765 (info, input_bfd, input_section, rel, howto,
2766 bfd_reloc_notsupported, is_undefweak, name,
2767 "Shouldn't be with r_addend."));
2768 break;
2771 relocation = sec_addr (plt) + h->plt.offset;
2772 unresolved_reloc = false;
2773 break;
2776 if (resolved_local)
2778 relocation += rel->r_addend;
2779 break;
2782 break;
2784 case R_LARCH_SOP_PUSH_PCREL:
2785 case R_LARCH_SOP_PUSH_PLT_PCREL:
2786 unresolved_reloc = false;
2788 if (is_undefweak)
2790 i = 0, j = 0;
2791 relocation = 0;
2792 if (resolved_dynly)
2794 if (h && h->plt.offset != MINUS_ONE)
2795 i = 1, j = 2;
2796 else
2797 fatal = (loongarch_reloc_is_fatal
2798 (info, input_bfd, input_section, rel, howto,
2799 bfd_reloc_dangerous, is_undefweak, name,
2800 "Undefweak need to be resolved dynamically, "
2801 "but PLT stub doesn't represent."));
2804 else
2806 if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
2808 fatal = (loongarch_reloc_is_fatal
2809 (info, input_bfd, input_section, rel, howto,
2810 bfd_reloc_undefined, is_undefweak, name,
2811 "PLT stub does not represent and "
2812 "symbol not defined."));
2813 break;
2816 if (resolved_local)
2817 i = 0, j = 2;
2818 else /* if (resolved_dynly) */
2820 if (!(h && h->plt.offset != MINUS_ONE))
2821 fatal = (loongarch_reloc_is_fatal
2822 (info, input_bfd, input_section, rel, howto,
2823 bfd_reloc_dangerous, is_undefweak, name,
2824 "Internal: PLT stub doesn't represent. "
2825 "Resolve it with pcrel"));
2826 i = 1, j = 3;
2830 for (; i < j; i++)
2832 if ((i & 1) == 0 && defined_local)
2834 relocation -= pc;
2835 relocation += rel->r_addend;
2836 break;
2839 if ((i & 1) && h && h->plt.offset != MINUS_ONE)
2841 if (rel->r_addend != 0)
2843 fatal = (loongarch_reloc_is_fatal
2844 (info, input_bfd, input_section, rel, howto,
2845 bfd_reloc_notsupported, is_undefweak, name,
2846 "PLT shouldn't be with r_addend."));
2847 break;
2849 relocation = sec_addr (plt) + h->plt.offset - pc;
2850 break;
2853 break;
2855 case R_LARCH_SOP_PUSH_GPREL:
2856 unresolved_reloc = false;
2858 if (rel->r_addend != 0)
2860 fatal = (loongarch_reloc_is_fatal
2861 (info, input_bfd, input_section, rel, howto,
2862 bfd_reloc_notsupported, is_undefweak, name,
2863 "Shouldn't be with r_addend."));
2864 break;
2867 if (h != NULL)
2869 off = h->got.offset & (~1);
2871 if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC)
2873 fatal = (loongarch_reloc_is_fatal
2874 (info, input_bfd, input_section, rel, howto,
2875 bfd_reloc_notsupported, is_undefweak, name,
2876 "Internal: GOT entry doesn't represent."));
2877 break;
2880 /* Hidden symbol not has .got entry, only .got.plt entry
2881 so gprel is (plt - got). */
2882 if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
2884 if (h->plt.offset == (bfd_vma) -1)
2886 abort();
2889 bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE;
2890 off = plt_index * GOT_ENTRY_SIZE;
2892 if (htab->elf.splt != NULL)
2894 /* Section .plt header is 2 times of plt entry. */
2895 off = sec_addr (htab->elf.sgotplt) + off
2896 - sec_addr (htab->elf.sgot);
2898 else
2900 /* Section iplt not has plt header. */
2901 off = sec_addr (htab->elf.igotplt) + off
2902 - sec_addr (htab->elf.sgot);
2906 if ((h->got.offset & 1) == 0)
2908 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
2909 bfd_link_pic (info), h)
2910 && ((bfd_link_pic (info)
2911 && SYMBOL_REFERENCES_LOCAL (info, h))))
2913 /* This is actually a static link, or it is a
2914 -Bsymbolic link and the symbol is defined
2915 locally, or the symbol was forced to be local
2916 because of a version file. We must initialize
2917 this entry in the global offset table. Since the
2918 offset must always be a multiple of the word size,
2919 we use the least significant bit to record whether
2920 we have initialized it already.
2922 When doing a dynamic link, we create a rela.got
2923 relocation entry to initialize the value. This
2924 is done in the finish_dynamic_symbol routine. */
2926 if (resolved_dynly)
2928 fatal = (loongarch_reloc_is_fatal
2929 (info, input_bfd, input_section, rel, howto,
2930 bfd_reloc_dangerous, is_undefweak, name,
2931 "Internal: here shouldn't dynamic."));
2934 if (!(defined_local || resolved_to_const))
2936 fatal = (loongarch_reloc_is_fatal
2937 (info, input_bfd, input_section, rel, howto,
2938 bfd_reloc_undefined, is_undefweak, name,
2939 "Internal: "));
2940 break;
2943 asection *s;
2944 Elf_Internal_Rela outrel;
2945 /* We need to generate a R_LARCH_RELATIVE reloc
2946 for the dynamic linker. */
2947 s = htab->elf.srelgot;
2948 if (!s)
2950 fatal = loongarch_reloc_is_fatal
2951 (info, input_bfd,
2952 input_section, rel, howto,
2953 bfd_reloc_notsupported, is_undefweak, name,
2954 "Internal: '.rel.got' not represent");
2955 break;
2958 outrel.r_offset = sec_addr (got) + off;
2959 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2960 outrel.r_addend = relocation; /* Link-time addr. */
2961 loongarch_elf_append_rela (output_bfd, s, &outrel);
2963 bfd_put_NN (output_bfd, relocation, got->contents + off);
2964 h->got.offset |= 1;
2967 else
2969 if (!local_got_offsets)
2971 fatal = (loongarch_reloc_is_fatal
2972 (info, input_bfd, input_section, rel, howto,
2973 bfd_reloc_notsupported, is_undefweak, name,
2974 "Internal: local got offsets not reporesent."));
2975 break;
2978 off = local_got_offsets[r_symndx] & (~1);
2980 if (local_got_offsets[r_symndx] == MINUS_ONE)
2982 fatal = (loongarch_reloc_is_fatal
2983 (info, input_bfd, input_section, rel, howto,
2984 bfd_reloc_notsupported, is_undefweak, name,
2985 "Internal: GOT entry doesn't represent."));
2986 break;
2989 /* The offset must always be a multiple of the word size.
2990 So, we can use the least significant bit to record
2991 whether we have already processed this entry. */
2992 if ((local_got_offsets[r_symndx] & 1) == 0)
2994 if (is_pic)
2996 asection *s;
2997 Elf_Internal_Rela outrel;
2998 /* We need to generate a R_LARCH_RELATIVE reloc
2999 for the dynamic linker. */
3000 s = htab->elf.srelgot;
3001 if (!s)
3003 fatal = (loongarch_reloc_is_fatal
3004 (info, input_bfd, input_section, rel, howto,
3005 bfd_reloc_notsupported, is_undefweak, name,
3006 "Internal: '.rel.got' not represent"));
3007 break;
3010 outrel.r_offset = sec_addr (got) + off;
3011 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3012 outrel.r_addend = relocation; /* Link-time addr. */
3013 loongarch_elf_append_rela (output_bfd, s, &outrel);
3016 bfd_put_NN (output_bfd, relocation, got->contents + off);
3017 local_got_offsets[r_symndx] |= 1;
3020 relocation = off;
3022 break;
3024 case R_LARCH_SOP_PUSH_TLS_GOT:
3025 case R_LARCH_SOP_PUSH_TLS_GD:
3027 unresolved_reloc = false;
3028 if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
3029 is_ie = true;
3031 bfd_vma got_off = 0;
3032 if (h != NULL)
3034 got_off = h->got.offset;
3035 h->got.offset |= 1;
3037 else
3039 got_off = local_got_offsets[r_symndx];
3040 local_got_offsets[r_symndx] |= 1;
3043 BFD_ASSERT (got_off != MINUS_ONE);
3045 ie_off = 0;
3046 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
3047 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3048 ie_off = 2 * GOT_ENTRY_SIZE;
3050 if ((got_off & 1) == 0)
3052 Elf_Internal_Rela rela;
3053 asection *srel = htab->elf.srelgot;
3054 bfd_vma tls_block_off = 0;
3056 if (SYMBOL_REFERENCES_LOCAL (info, h))
3058 BFD_ASSERT (elf_hash_table (info)->tls_sec);
3059 tls_block_off = relocation
3060 - elf_hash_table (info)->tls_sec->vma;
3063 if (tls_type & GOT_TLS_GD)
3065 rela.r_offset = sec_addr (got) + got_off;
3066 rela.r_addend = 0;
3067 if (SYMBOL_REFERENCES_LOCAL (info, h))
3069 /* Local sym, used in exec, set module id 1. */
3070 if (bfd_link_executable (info))
3071 bfd_put_NN (output_bfd, 1, got->contents + got_off);
3072 else
3074 rela.r_info = ELFNN_R_INFO (0,
3075 R_LARCH_TLS_DTPMODNN);
3076 loongarch_elf_append_rela (output_bfd, srel, &rela);
3079 bfd_put_NN (output_bfd, tls_block_off,
3080 got->contents + got_off + GOT_ENTRY_SIZE);
3082 /* Dynamic resolved. */
3083 else
3085 /* Dynamic relocate module id. */
3086 rela.r_info = ELFNN_R_INFO (h->dynindx,
3087 R_LARCH_TLS_DTPMODNN);
3088 loongarch_elf_append_rela (output_bfd, srel, &rela);
3090 /* Dynamic relocate offset of block. */
3091 rela.r_offset += GOT_ENTRY_SIZE;
3092 rela.r_info = ELFNN_R_INFO (h->dynindx,
3093 R_LARCH_TLS_DTPRELNN);
3094 loongarch_elf_append_rela (output_bfd, srel, &rela);
3097 if (tls_type & GOT_TLS_IE)
3099 rela.r_offset = sec_addr (got) + got_off + ie_off;
3100 if (SYMBOL_REFERENCES_LOCAL (info, h))
3102 /* Local sym, used in exec, set module id 1. */
3103 if (!bfd_link_executable (info))
3105 rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
3106 rela.r_addend = tls_block_off;
3107 loongarch_elf_append_rela (output_bfd, srel, &rela);
3110 bfd_put_NN (output_bfd, tls_block_off,
3111 got->contents + got_off + ie_off);
3113 /* Dynamic resolved. */
3114 else
3116 /* Dynamic relocate offset of block. */
3117 rela.r_info = ELFNN_R_INFO (h->dynindx,
3118 R_LARCH_TLS_TPRELNN);
3119 rela.r_addend = 0;
3120 loongarch_elf_append_rela (output_bfd, srel, &rela);
3125 relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0);
3127 break;
3129 /* New reloc types. */
3130 case R_LARCH_B21:
3131 case R_LARCH_B26:
3132 case R_LARCH_B16:
3133 unresolved_reloc = false;
3134 if (is_undefweak)
3136 relocation = 0;
3139 if (resolved_local)
3141 relocation -= pc;
3142 relocation += rel->r_addend;
3144 else if (resolved_dynly)
3146 BFD_ASSERT (h
3147 && (h->plt.offset != MINUS_ONE
3148 || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
3149 && rel->r_addend == 0);
3150 if (h && h->plt.offset == MINUS_ONE
3151 && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
3153 relocation -= pc;
3154 relocation += rel->r_addend;
3156 else
3157 relocation = sec_addr (plt) + h->plt.offset - pc;
3160 break;
3162 case R_LARCH_ABS_HI20:
3163 case R_LARCH_ABS_LO12:
3164 case R_LARCH_ABS64_LO20:
3165 case R_LARCH_ABS64_HI12:
3166 BFD_ASSERT (!is_pic);
3168 if (is_undefweak)
3170 BFD_ASSERT (resolved_dynly);
3171 relocation = 0;
3172 break;
3174 else if (resolved_to_const || resolved_local)
3176 relocation += rel->r_addend;
3178 else if (resolved_dynly)
3180 unresolved_reloc = false;
3181 BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE)
3182 && rel->r_addend == 0);
3183 relocation = sec_addr (plt) + h->plt.offset;
3186 break;
3188 case R_LARCH_PCREL20_S2:
3189 unresolved_reloc = false;
3190 if (h && h->plt.offset != MINUS_ONE)
3191 relocation = sec_addr (plt) + h->plt.offset;
3192 else
3193 relocation += rel->r_addend;
3194 relocation -= pc;
3195 break;
3197 case R_LARCH_PCALA_HI20:
3198 unresolved_reloc = false;
3199 if (h && h->plt.offset != MINUS_ONE)
3200 relocation = sec_addr (plt) + h->plt.offset;
3201 else
3202 relocation += rel->r_addend;
3204 RELOCATE_CALC_PC32_HI20 (relocation, pc);
3206 break;
3208 case R_LARCH_PCALA_LO12:
3209 /* Not support if sym_addr in 2k page edge.
3210 pcalau12i pc_hi20 (sym_addr)
3211 ld.w/d pc_lo12 (sym_addr)
3212 ld.w/d pc_lo12 (sym_addr + x)
3214 can not calc correct address
3215 if sym_addr < 0x800 && sym_addr + x >= 0x800. */
3217 if (h && h->plt.offset != MINUS_ONE)
3218 relocation = sec_addr (plt) + h->plt.offset;
3219 else
3220 relocation += rel->r_addend;
3222 /* For 2G jump, generate pcalau12i, jirl. */
3223 /* If use jirl, turns to R_LARCH_B16. */
3224 uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
3225 if ((insn & 0x4c000000) == 0x4c000000)
3227 relocation &= 0xfff;
3228 /* Signed extend. */
3229 relocation = (relocation ^ 0x800) - 0x800;
3231 rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
3232 howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
3234 break;
3236 case R_LARCH_PCALA64_LO20:
3237 case R_LARCH_PCALA64_HI12:
3238 if (h && h->plt.offset != MINUS_ONE)
3239 relocation = sec_addr (plt) + h->plt.offset;
3240 else
3241 relocation += rel->r_addend;
3243 RELOCATE_CALC_PC64_HI32 (relocation, pc);
3245 break;
3247 case R_LARCH_GOT_PC_HI20:
3248 case R_LARCH_GOT_HI20:
3249 /* Calc got offset. */
3251 unresolved_reloc = false;
3252 BFD_ASSERT (rel->r_addend == 0);
3254 bfd_vma got_off = 0;
3255 if (h != NULL)
3257 /* GOT ref or ifunc. */
3258 BFD_ASSERT (h->got.offset != MINUS_ONE
3259 || h->type == STT_GNU_IFUNC);
3261 got_off = h->got.offset & (~(bfd_vma)1);
3262 /* Hidden symbol not has got entry,
3263 * only got.plt entry so it is (plt - got). */
3264 if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
3266 bfd_vma idx;
3267 if (htab->elf.splt != NULL)
3269 idx = (h->plt.offset - PLT_HEADER_SIZE)
3270 / PLT_ENTRY_SIZE;
3271 got_off = sec_addr (htab->elf.sgotplt)
3272 + GOTPLT_HEADER_SIZE
3273 + (idx * GOT_ENTRY_SIZE)
3274 - sec_addr (htab->elf.sgot);
3276 else
3278 idx = h->plt.offset / PLT_ENTRY_SIZE;
3279 got_off = sec_addr (htab->elf.sgotplt)
3280 + (idx * GOT_ENTRY_SIZE)
3281 - sec_addr (htab->elf.sgot);
3285 if ((h->got.offset & 1) == 0)
3287 /* We need to generate a R_LARCH_RELATIVE reloc once
3288 * in loongarch_elf_finish_dynamic_symbol or now,
3289 * call finish_dyn && nopic
3290 * or !call finish_dyn && pic. */
3291 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
3292 bfd_link_pic (info),
3294 && bfd_link_pic (info)
3295 && SYMBOL_REFERENCES_LOCAL (info, h))
3297 Elf_Internal_Rela rela;
3298 rela.r_offset = sec_addr (got) + got_off;
3299 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3300 rela.r_addend = relocation;
3301 loongarch_elf_append_rela (output_bfd,
3302 htab->elf.srelgot, &rela);
3304 h->got.offset |= 1;
3305 bfd_put_NN (output_bfd, relocation,
3306 got->contents + got_off);
3309 else
3311 BFD_ASSERT (local_got_offsets
3312 && local_got_offsets[r_symndx] != MINUS_ONE);
3314 got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
3315 if ((local_got_offsets[r_symndx] & 1) == 0)
3317 if (bfd_link_pic (info))
3319 Elf_Internal_Rela rela;
3320 rela.r_offset = sec_addr (got) + got_off;
3321 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3322 rela.r_addend = relocation;
3323 loongarch_elf_append_rela (output_bfd,
3324 htab->elf.srelgot, &rela);
3326 local_got_offsets[r_symndx] |= 1;
3328 bfd_put_NN (output_bfd, relocation, got->contents + got_off);
3331 relocation = got_off + sec_addr (got);
3334 if (r_type == R_LARCH_GOT_PC_HI20)
3335 RELOCATE_CALC_PC32_HI20 (relocation, pc);
3337 break;
3339 case R_LARCH_GOT_PC_LO12:
3340 case R_LARCH_GOT64_PC_LO20:
3341 case R_LARCH_GOT64_PC_HI12:
3342 case R_LARCH_GOT_LO12:
3343 case R_LARCH_GOT64_LO20:
3344 case R_LARCH_GOT64_HI12:
3346 unresolved_reloc = false;
3347 bfd_vma got_off;
3348 if (h)
3349 got_off = h->got.offset & (~(bfd_vma)1);
3350 else
3351 got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
3353 if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
3355 bfd_vma idx;
3356 if (htab->elf.splt != NULL)
3357 idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
3358 else
3359 idx = h->plt.offset / PLT_ENTRY_SIZE;
3361 got_off = sec_addr (htab->elf.sgotplt)
3362 + GOTPLT_HEADER_SIZE
3363 + (idx * GOT_ENTRY_SIZE)
3364 - sec_addr (htab->elf.sgot);
3367 relocation = got_off + sec_addr (got);
3370 if (r_type == R_LARCH_GOT64_PC_HI12
3371 || r_type == R_LARCH_GOT64_PC_LO20)
3372 RELOCATE_CALC_PC64_HI32 (relocation, pc);
3374 break;
3376 case R_LARCH_TLS_LE_HI20:
3377 case R_LARCH_TLS_LE_LO12:
3378 case R_LARCH_TLS_LE64_LO20:
3379 case R_LARCH_TLS_LE64_HI12:
3380 BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
3382 relocation -= elf_hash_table (info)->tls_sec->vma;
3383 break;
3385 /* TLS IE LD/GD process separately is troublesome.
3386 When a symbol is both ie and LD/GD, h->got.off |= 1
3387 make only one type be relocated. We must use
3388 h->got.offset |= 1 and h->got.offset |= 2
3389 diff IE and LD/GD. And all (got_off & (~(bfd_vma)1))
3390 (IE LD/GD and reusable GOT reloc) must change to
3391 (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
3392 as a tag.
3393 Now, LD and GD is both GOT_TLS_GD type, LD seems to
3394 can be omitted. */
3395 case R_LARCH_TLS_IE_PC_HI20:
3396 case R_LARCH_TLS_IE_HI20:
3397 case R_LARCH_TLS_LD_PC_HI20:
3398 case R_LARCH_TLS_LD_HI20:
3399 case R_LARCH_TLS_GD_PC_HI20:
3400 case R_LARCH_TLS_GD_HI20:
3401 BFD_ASSERT (rel->r_addend == 0);
3402 unresolved_reloc = false;
3404 if (r_type == R_LARCH_TLS_IE_PC_HI20
3405 || r_type == R_LARCH_TLS_IE_HI20)
3406 is_ie = true;
3408 bfd_vma got_off = 0;
3409 if (h != NULL)
3411 got_off = h->got.offset;
3412 h->got.offset |= 1;
3414 else
3416 got_off = local_got_offsets[r_symndx];
3417 local_got_offsets[r_symndx] |= 1;
3420 BFD_ASSERT (got_off != MINUS_ONE);
3422 ie_off = 0;
3423 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
3424 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3425 ie_off = 2 * GOT_ENTRY_SIZE;
3427 if ((got_off & 1) == 0)
3429 Elf_Internal_Rela rela;
3430 asection *relgot = htab->elf.srelgot;
3431 bfd_vma tls_block_off = 0;
3433 if (SYMBOL_REFERENCES_LOCAL (info, h))
3435 BFD_ASSERT (elf_hash_table (info)->tls_sec);
3436 tls_block_off = relocation
3437 - elf_hash_table (info)->tls_sec->vma;
3440 if (tls_type & GOT_TLS_GD)
3442 rela.r_offset = sec_addr (got) + got_off;
3443 rela.r_addend = 0;
3444 if (SYMBOL_REFERENCES_LOCAL (info, h))
3446 /* Local sym, used in exec, set module id 1. */
3447 if (bfd_link_executable (info))
3448 bfd_put_NN (output_bfd, 1, got->contents + got_off);
3449 else
3451 rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
3452 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3455 bfd_put_NN (output_bfd, tls_block_off,
3456 got->contents + got_off + GOT_ENTRY_SIZE);
3458 /* Dynamic resolved. */
3459 else
3461 /* Dynamic relocate module id. */
3462 rela.r_info = ELFNN_R_INFO (h->dynindx,
3463 R_LARCH_TLS_DTPMODNN);
3464 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3466 /* Dynamic relocate offset of block. */
3467 rela.r_offset += GOT_ENTRY_SIZE;
3468 rela.r_info = ELFNN_R_INFO (h->dynindx,
3469 R_LARCH_TLS_DTPRELNN);
3470 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3473 if (tls_type & GOT_TLS_IE)
3475 rela.r_offset = sec_addr (got) + got_off + ie_off;
3476 if (SYMBOL_REFERENCES_LOCAL (info, h))
3478 /* Local sym, used in exec, set module id 1. */
3479 if (!bfd_link_executable (info))
3481 rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
3482 rela.r_addend = tls_block_off;
3483 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3486 bfd_put_NN (output_bfd, tls_block_off,
3487 got->contents + got_off + ie_off);
3489 /* Dynamic resolved. */
3490 else
3492 /* Dynamic relocate offset of block. */
3493 rela.r_info = ELFNN_R_INFO (h->dynindx,
3494 R_LARCH_TLS_TPRELNN);
3495 rela.r_addend = 0;
3496 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3500 relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
3501 + (is_ie ? ie_off : 0);
3503 if (r_type == R_LARCH_TLS_LD_PC_HI20
3504 || r_type == R_LARCH_TLS_GD_PC_HI20
3505 || r_type == R_LARCH_TLS_IE_PC_HI20)
3506 RELOCATE_CALC_PC32_HI20 (relocation, pc);
3508 break;
3510 case R_LARCH_TLS_IE_PC_LO12:
3511 case R_LARCH_TLS_IE64_PC_LO20:
3512 case R_LARCH_TLS_IE64_PC_HI12:
3513 case R_LARCH_TLS_IE_LO12:
3514 case R_LARCH_TLS_IE64_LO20:
3515 case R_LARCH_TLS_IE64_HI12:
3516 unresolved_reloc = false;
3518 if (h)
3519 relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
3520 else
3521 relocation = sec_addr (got)
3522 + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
3524 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
3525 /* Use both TLS_GD and TLS_IE. */
3526 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3527 relocation += 2 * GOT_ENTRY_SIZE;
3529 if (r_type == R_LARCH_TLS_IE64_PC_LO20
3530 || r_type == R_LARCH_TLS_IE64_PC_HI12)
3531 RELOCATE_CALC_PC64_HI32 (relocation, pc);
3533 break;
3535 case R_LARCH_RELAX:
3536 case R_LARCH_ALIGN:
3537 r = bfd_reloc_continue;
3538 unresolved_reloc = false;
3539 break;
3541 default:
3542 break;
3545 if (fatal)
3546 break;
3550 /* 'unresolved_reloc' means we haven't done it yet.
3551 We need help of dynamic linker to fix this memory location up. */
3552 if (!unresolved_reloc)
3553 break;
3555 if (_bfd_elf_section_offset (output_bfd, info, input_section,
3556 rel->r_offset) == MINUS_ONE)
3557 /* WHY? May because it's invalid so skip checking.
3558 But why dynamic reloc a invalid section? */
3559 break;
3561 if (input_section->output_section->flags & SEC_DEBUGGING)
3563 fatal = (loongarch_reloc_is_fatal
3564 (info, input_bfd, input_section, rel, howto,
3565 bfd_reloc_dangerous, is_undefweak, name,
3566 "Seems dynamic linker not process "
3567 "sections 'SEC_DEBUGGING'."));
3569 if (!is_dyn)
3570 break;
3572 if ((info->flags & DF_TEXTREL) == 0)
3573 if (input_section->output_section->flags & SEC_READONLY)
3574 info->flags |= DF_TEXTREL;
3576 while (0);
3578 if (fatal)
3579 break;
3581 loongarch_record_one_reloc (input_bfd, input_section, r_type,
3582 rel->r_offset, sym, h, rel->r_addend);
3584 if (r != bfd_reloc_continue)
3585 r = perform_relocation (rel, input_section, howto, relocation,
3586 input_bfd, contents);
3588 switch (r)
3590 case bfd_reloc_dangerous:
3591 case bfd_reloc_continue:
3592 case bfd_reloc_ok:
3593 continue;
3595 case bfd_reloc_overflow:
3596 /* Overflow value can't be filled in. */
3597 loongarch_dump_reloc_record (info->callbacks->info);
3598 info->callbacks->reloc_overflow
3599 (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
3600 input_bfd, input_section, rel->r_offset);
3601 break;
3603 case bfd_reloc_outofrange:
3604 /* Stack state incorrect. */
3605 loongarch_dump_reloc_record (info->callbacks->info);
3606 info->callbacks->info
3607 ("%X%H: Internal stack state is incorrect.\n"
3608 "Want to push to full stack or pop from empty stack?\n",
3609 input_bfd, input_section, rel->r_offset);
3610 break;
3612 case bfd_reloc_notsupported:
3613 info->callbacks->info ("%X%H: Unknown relocation type.\n", input_bfd,
3614 input_section, rel->r_offset);
3615 break;
3617 default:
3618 info->callbacks->info ("%X%H: Internal: unknown error.\n", input_bfd,
3619 input_section, rel->r_offset);
3620 break;
3623 fatal = true;
3626 return !fatal;
3629 static bool
3630 loongarch_relax_delete_bytes (bfd *abfd,
3631 asection *sec,
3632 bfd_vma addr,
3633 size_t count,
3634 struct bfd_link_info *link_info)
3636 unsigned int i, symcount;
3637 bfd_vma toaddr = sec->size;
3638 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
3639 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
3640 unsigned int sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
3641 struct bfd_elf_section_data *data = elf_section_data (sec);
3642 bfd_byte *contents = data->this_hdr.contents;
3644 /* Actually delete the bytes. */
3645 sec->size -= count;
3646 memmove (contents + addr, contents + addr + count, toaddr - addr - count);
3648 /* Adjust the location of all of the relocs. Note that we need not
3649 adjust the addends, since all PC-relative references must be against
3650 symbols, which we will adjust below. */
3651 for (i = 0; i < sec->reloc_count; i++)
3652 if (data->relocs[i].r_offset > addr && data->relocs[i].r_offset < toaddr)
3653 data->relocs[i].r_offset -= count;
3655 /* Adjust the local symbols defined in this section. */
3656 for (i = 0; i < symtab_hdr->sh_info; i++)
3658 Elf_Internal_Sym *sym = (Elf_Internal_Sym *) symtab_hdr->contents + i;
3659 if (sym->st_shndx == sec_shndx)
3661 /* If the symbol is in the range of memory we just moved, we
3662 have to adjust its value. */
3663 if (sym->st_value > addr && sym->st_value <= toaddr)
3664 sym->st_value -= count;
3666 /* If the symbol *spans* the bytes we just deleted (i.e. its
3667 *end* is in the moved bytes but its *start* isn't), then we
3668 must adjust its size.
3670 This test needs to use the original value of st_value, otherwise
3671 we might accidentally decrease size when deleting bytes right
3672 before the symbol. But since deleted relocs can't span across
3673 symbols, we can't have both a st_value and a st_size decrease,
3674 so it is simpler to just use an else. */
3675 else if (sym->st_value <= addr
3676 && sym->st_value + sym->st_size > addr
3677 && sym->st_value + sym->st_size <= toaddr)
3678 sym->st_size -= count;
3682 /* Now adjust the global symbols defined in this section. */
3683 symcount = ((symtab_hdr->sh_size / sizeof (ElfNN_External_Sym))
3684 - symtab_hdr->sh_info);
3686 for (i = 0; i < symcount; i++)
3688 struct elf_link_hash_entry *sym_hash = sym_hashes[i];
3690 /* The '--wrap SYMBOL' option is causing a pain when the object file,
3691 containing the definition of __wrap_SYMBOL, includes a direct
3692 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
3693 the same symbol (which is __wrap_SYMBOL), but still exist as two
3694 different symbols in 'sym_hashes', we don't want to adjust
3695 the global symbol __wrap_SYMBOL twice.
3697 The same problem occurs with symbols that are versioned_hidden, as
3698 foo becomes an alias for foo@BAR, and hence they need the same
3699 treatment. */
3700 if (link_info->wrap_hash != NULL
3701 || sym_hash->versioned != unversioned)
3703 struct elf_link_hash_entry **cur_sym_hashes;
3705 /* Loop only over the symbols which have already been checked. */
3706 for (cur_sym_hashes = sym_hashes; cur_sym_hashes < &sym_hashes[i];
3707 cur_sym_hashes++)
3709 /* If the current symbol is identical to 'sym_hash', that means
3710 the symbol was already adjusted (or at least checked). */
3711 if (*cur_sym_hashes == sym_hash)
3712 break;
3714 /* Don't adjust the symbol again. */
3715 if (cur_sym_hashes < &sym_hashes[i])
3716 continue;
3719 if ((sym_hash->root.type == bfd_link_hash_defined
3720 || sym_hash->root.type == bfd_link_hash_defweak)
3721 && sym_hash->root.u.def.section == sec)
3723 /* As above, adjust the value if needed. */
3724 if (sym_hash->root.u.def.value > addr
3725 && sym_hash->root.u.def.value <= toaddr)
3726 sym_hash->root.u.def.value -= count;
3728 /* As above, adjust the size if needed. */
3729 else if (sym_hash->root.u.def.value <= addr
3730 && sym_hash->root.u.def.value + sym_hash->size > addr
3731 && sym_hash->root.u.def.value + sym_hash->size <= toaddr)
3732 sym_hash->size -= count;
3736 return true;
3739 /* Relax pcalau12i,addi.d => pcaddi. */
3740 static bool
3741 loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
3742 Elf_Internal_Rela *rel_hi, bfd_vma symval,
3743 struct bfd_link_info *info, bool *again)
3745 bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
3746 Elf_Internal_Rela *rel_lo = rel_hi + 2;
3747 uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
3748 uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
3749 uint32_t rd = pca & 0x1f;
3751 /* This section's output_offset need to subtract the bytes of instructions
3752 relaxed by the previous sections, so it needs to be updated beforehand.
3753 size_input_section already took care of updating it after relaxation,
3754 so we additionally update once here. */
3755 sec->output_offset = sec->output_section->size;
3756 bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
3758 /* If pc and symbol not in the same segment, add/sub segment alignment.
3759 FIXME: if there are multiple readonly segments? */
3760 if (!(sym_sec->flags & SEC_READONLY))
3762 if (symval > pc)
3763 pc -= info->maxpagesize;
3764 else if (symval < pc)
3765 pc += info->maxpagesize;
3768 const uint32_t addi_d = 0x02c00000;
3769 const uint32_t pcaddi = 0x18000000;
3771 /* Is pcalau12i + addi.d insns? */
3772 if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12)
3773 || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
3774 || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
3775 || (rel_hi->r_offset + 4 != rel_lo->r_offset)
3776 || ((add & addi_d) != addi_d)
3777 /* Is pcalau12i $rd + addi.d $rd,$rd? */
3778 || ((add & 0x1f) != rd)
3779 || (((add >> 5) & 0x1f) != rd)
3780 /* Can be relaxed to pcaddi? */
3781 || (symval & 0x3) /* 4 bytes align. */
3782 || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
3783 || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x1ffffc))
3784 return false;
3786 /* Continue next relax trip. */
3787 *again = true;
3789 pca = pcaddi | rd;
3790 bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
3792 /* Adjust relocations. */
3793 rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
3794 R_LARCH_PCREL20_S2);
3795 rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
3797 loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
3799 return true;
3802 /* Relax pcalau12i,ld.d => pcalau12i,addi.d. */
3803 static bool
3804 loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
3805 Elf_Internal_Rela *rel_hi)
3807 bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
3808 Elf_Internal_Rela *rel_lo = rel_hi + 2;
3809 uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
3810 uint32_t ld = bfd_get (32, abfd, contents + rel_lo->r_offset);
3811 uint32_t rd = pca & 0x1f;
3812 const uint32_t ld_d = 0x28c00000;
3813 uint32_t addi_d = 0x02c00000;
3815 if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
3816 || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
3817 || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
3818 || (rel_hi->r_offset + 4 != rel_lo->r_offset)
3819 || ((ld & 0x1f) != rd)
3820 || (((ld >> 5) & 0x1f) != rd)
3821 || ((ld & ld_d) != ld_d))
3822 return false;
3824 addi_d = addi_d | (rd << 5) | rd;
3825 bfd_put (32, abfd, addi_d, contents + rel_lo->r_offset);
3827 rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
3828 R_LARCH_PCALA_HI20);
3829 rel_lo->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_lo->r_info),
3830 R_LARCH_PCALA_LO12);
3831 return true;
3834 /* Called by after_allocation to set the information of data segment
3835 before relaxing. */
3837 void
3838 bfd_elfNN_loongarch_set_data_segment_info (struct bfd_link_info *info,
3839 int *data_segment_phase)
3841 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
3842 htab->data_segment_phase = data_segment_phase;
3845 /* Implement R_LARCH_ALIGN by deleting excess alignment NOPs.
3846 Once we've handled an R_LARCH_ALIGN, we can't relax anything else. */
3847 static bool
3848 loongarch_relax_align (bfd *abfd, asection *sec,
3849 asection *sym_sec,
3850 struct bfd_link_info *link_info,
3851 Elf_Internal_Rela *rel,
3852 bfd_vma symval)
3854 bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
3855 bfd_vma alignment = 1, pos;
3856 while (alignment <= rel->r_addend)
3857 alignment *= 2;
3859 symval -= rel->r_addend;
3860 bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
3861 bfd_vma nop_bytes = aligned_addr - symval;
3863 /* Once we've handled an R_LARCH_ALIGN, we can't relax anything else. */
3864 sec->sec_flg0 = true;
3866 /* Make sure there are enough NOPs to actually achieve the alignment. */
3867 if (rel->r_addend < nop_bytes)
3869 _bfd_error_handler
3870 (_("%pB(%pA+%#" PRIx64 "): %" PRId64 " bytes required for alignment "
3871 "to %" PRId64 "-byte boundary, but only %" PRId64 " present"),
3872 abfd, sym_sec, (uint64_t) rel->r_offset,
3873 (int64_t) nop_bytes, (int64_t) alignment, (int64_t) rel->r_addend);
3874 bfd_set_error (bfd_error_bad_value);
3875 return false;
3878 /* Delete the reloc. */
3879 rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
3881 /* If the number of NOPs is already correct, there's nothing to do. */
3882 if (nop_bytes == rel->r_addend)
3883 return true;
3885 /* Write as many LOONGARCH NOPs as we need. */
3886 for (pos = 0; pos < (nop_bytes & -4); pos += 4)
3887 bfd_putl32 (LARCH_NOP, contents + rel->r_offset + pos);
3889 /* Delete the excess NOPs. */
3890 return loongarch_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
3891 rel->r_addend - nop_bytes, link_info);
3894 static bool
3895 loongarch_elf_relax_section (bfd *abfd, asection *sec,
3896 struct bfd_link_info *info,
3897 bool *again)
3899 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
3900 Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
3901 struct bfd_elf_section_data *data = elf_section_data (sec);
3902 Elf_Internal_Rela *relocs;
3903 *again = false;
3905 if (bfd_link_relocatable (info)
3906 || sec->sec_flg0
3907 || (sec->flags & SEC_RELOC) == 0
3908 || sec->reloc_count == 0
3909 || (info->disable_target_specific_optimizations
3910 && info->relax_pass == 0)
3911 /* The exp_seg_relro_adjust is enum phase_enum (0x4),
3912 and defined in ld/ldexp.h. */
3913 || *(htab->data_segment_phase) == 4)
3914 return true;
3916 if (data->relocs)
3917 relocs = data->relocs;
3918 else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
3919 info->keep_memory)))
3920 return true;
3922 if (!data->this_hdr.contents
3923 && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents))
3924 return true;
3926 if (symtab_hdr->sh_info != 0
3927 && !symtab_hdr->contents
3928 && !(symtab_hdr->contents =
3929 (unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr,
3930 symtab_hdr->sh_info,
3931 0, NULL, NULL, NULL)))
3932 return true;
3934 data->relocs = relocs;
3936 for (unsigned int i = 0; i < sec->reloc_count; i++)
3938 Elf_Internal_Rela *rel = relocs + i;
3939 asection *sym_sec;
3940 bfd_vma symval;
3941 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
3942 bool local_got = false;
3943 char symtype;
3944 struct elf_link_hash_entry *h = NULL;
3946 if (r_symndx < symtab_hdr->sh_info)
3948 Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
3949 + r_symndx;
3950 if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
3951 continue;
3953 if (sym->st_shndx == SHN_UNDEF)
3955 sym_sec = sec;
3956 symval = rel->r_offset;
3958 else
3960 sym_sec = elf_elfsections (abfd)[sym->st_shndx]->bfd_section;
3961 symval = sym->st_value;
3963 symtype = ELF_ST_TYPE (sym->st_info);
3965 else
3967 r_symndx = ELFNN_R_SYM (rel->r_info) - symtab_hdr->sh_info;
3968 h = elf_sym_hashes (abfd)[r_symndx];
3970 while (h->root.type == bfd_link_hash_indirect
3971 || h->root.type == bfd_link_hash_warning)
3972 h = (struct elf_link_hash_entry *) h->root.u.i.link;
3974 /* Disable the relaxation for ifunc. */
3975 if (h != NULL && h->type == STT_GNU_IFUNC)
3976 continue;
3978 if ((h->root.type == bfd_link_hash_defined
3979 || h->root.type == bfd_link_hash_defweak)
3980 && h->root.u.def.section != NULL
3981 && h->root.u.def.section->output_section != NULL)
3983 symval = h->root.u.def.value;
3984 sym_sec = h->root.u.def.section;
3986 else
3987 continue;
3989 if (h && bfd_link_executable (info)
3990 && SYMBOL_REFERENCES_LOCAL (info, h))
3991 local_got = true;
3992 symtype = h->type;
3995 if (sym_sec->sec_info_type == SEC_INFO_TYPE_MERGE
3996 && (sym_sec->flags & SEC_MERGE))
3998 if (symtype == STT_SECTION)
3999 symval += rel->r_addend;
4001 symval = _bfd_merged_section_offset (abfd, &sym_sec,
4002 elf_section_data (sym_sec)->sec_info,
4003 symval);
4005 if (symtype != STT_SECTION)
4006 symval += rel->r_addend;
4008 else
4009 symval += rel->r_addend;
4011 symval += sec_addr (sym_sec);
4013 switch (ELFNN_R_TYPE (rel->r_info))
4015 case R_LARCH_ALIGN:
4016 if (1 == info->relax_pass)
4017 loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval);
4018 break;
4019 case R_LARCH_DELETE:
4020 if (1 == info->relax_pass)
4022 loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info);
4023 rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
4025 break;
4026 case R_LARCH_PCALA_HI20:
4027 if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
4028 loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
4029 info, again);
4030 break;
4031 case R_LARCH_GOT_PC_HI20:
4032 if (local_got && 0 == info->relax_pass
4033 && (i + 4) <= sec->reloc_count)
4035 if (loongarch_relax_pcala_ld (abfd, sec, rel))
4036 loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
4037 info, again);
4039 break;
4040 default:
4041 break;
4045 return true;
4048 /* Finish up dynamic symbol handling. We set the contents of various
4049 dynamic sections here. */
4051 static bool
4052 loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
4053 struct bfd_link_info *info,
4054 struct elf_link_hash_entry *h,
4055 Elf_Internal_Sym *sym)
4057 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
4058 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
4060 if (h->plt.offset != MINUS_ONE)
4062 size_t i, plt_idx;
4063 asection *plt, *gotplt, *relplt;
4064 bfd_vma got_address;
4065 uint32_t plt_entry[PLT_ENTRY_INSNS];
4066 bfd_byte *loc;
4067 Elf_Internal_Rela rela;
4069 if (htab->elf.splt)
4071 BFD_ASSERT ((h->type == STT_GNU_IFUNC
4072 && SYMBOL_REFERENCES_LOCAL (info, h))
4073 || h->dynindx != -1);
4075 plt = htab->elf.splt;
4076 gotplt = htab->elf.sgotplt;
4077 if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
4078 relplt = htab->elf.srelgot;
4079 else
4080 relplt = htab->elf.srelplt;
4081 plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
4082 got_address =
4083 sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
4085 else /* if (htab->elf.iplt) */
4087 BFD_ASSERT (h->type == STT_GNU_IFUNC
4088 && SYMBOL_REFERENCES_LOCAL (info, h));
4090 plt = htab->elf.iplt;
4091 gotplt = htab->elf.igotplt;
4092 relplt = htab->elf.irelplt;
4093 plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
4094 got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
4097 /* Find out where the .plt entry should go. */
4098 loc = plt->contents + h->plt.offset;
4100 /* Fill in the PLT entry itself. */
4101 if (!loongarch_make_plt_entry (got_address,
4102 sec_addr (plt) + h->plt.offset,
4103 plt_entry))
4104 return false;
4106 for (i = 0; i < PLT_ENTRY_INSNS; i++)
4107 bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
4109 /* Fill in the initial value of the got.plt entry. */
4110 loc = gotplt->contents + (got_address - sec_addr (gotplt));
4111 bfd_put_NN (output_bfd, sec_addr (plt), loc);
4113 rela.r_offset = got_address;
4115 /* TRUE if this is a PLT reference to a local IFUNC. */
4116 if (PLT_LOCAL_IFUNC_P (info, h)
4117 && (relplt == htab->elf.srelgot
4118 || relplt == htab->elf.irelplt))
4120 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
4121 rela.r_addend = (h->root.u.def.value
4122 + h->root.u.def.section->output_section->vma
4123 + h->root.u.def.section->output_offset);
4125 loongarch_elf_append_rela (output_bfd, relplt, &rela);
4127 else
4129 /* Fill in the entry in the rela.plt section. */
4130 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
4131 rela.r_addend = 0;
4132 loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
4133 bed->s->swap_reloca_out (output_bfd, &rela, loc);
4136 if (!h->def_regular)
4138 /* Mark the symbol as undefined, rather than as defined in
4139 the .plt section. Leave the value alone. */
4140 sym->st_shndx = SHN_UNDEF;
4141 /* If the symbol is weak, we do need to clear the value.
4142 Otherwise, the PLT entry would provide a definition for
4143 the symbol even if the symbol wasn't defined anywhere,
4144 and so the symbol would never be NULL. */
4145 if (!h->ref_regular_nonweak)
4146 sym->st_value = 0;
4150 if (h->got.offset != MINUS_ONE
4151 /* TLS got entry have been handled in elf_relocate_section. */
4152 && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
4153 /* Have allocated got entry but not allocated rela before. */
4154 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
4156 asection *sgot, *srela;
4157 Elf_Internal_Rela rela;
4158 bfd_vma off = h->got.offset & ~(bfd_vma)1;
4160 /* This symbol has an entry in the GOT. Set it up. */
4161 sgot = htab->elf.sgot;
4162 srela = htab->elf.srelgot;
4163 BFD_ASSERT (sgot && srela);
4165 rela.r_offset = sec_addr (sgot) + off;
4167 if (h->def_regular
4168 && h->type == STT_GNU_IFUNC)
4170 if(h->plt.offset == MINUS_ONE)
4172 if (htab->elf.splt == NULL)
4173 srela = htab->elf.irelplt;
4175 if (SYMBOL_REFERENCES_LOCAL (info, h))
4177 asection *sec = h->root.u.def.section;
4178 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
4179 rela.r_addend = h->root.u.def.value + sec->output_section->vma
4180 + sec->output_offset;
4181 bfd_put_NN (output_bfd, 0, sgot->contents + off);
4183 else
4185 BFD_ASSERT (h->dynindx != -1);
4186 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
4187 rela.r_addend = 0;
4188 bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off);
4191 else if(bfd_link_pic (info))
4193 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
4194 rela.r_addend = 0;
4195 bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
4197 else
4199 asection *plt;
4200 /* For non-shared object, we can't use .got.plt, which
4201 contains the real function address if we need pointer
4202 equality. We load the GOT entry with the PLT entry. */
4203 plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
4204 bfd_put_NN (output_bfd,
4205 (plt->output_section->vma
4206 + plt->output_offset
4207 + h->plt.offset),
4208 sgot->contents + off);
4209 return true;
4212 else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
4214 asection *sec = h->root.u.def.section;
4215 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
4216 rela.r_addend = (h->root.u.def.value + sec->output_section->vma
4217 + sec->output_offset);
4219 else
4221 BFD_ASSERT (h->dynindx != -1);
4222 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
4223 rela.r_addend = 0;
4226 loongarch_elf_append_rela (output_bfd, srela, &rela);
4229 /* Mark some specially defined symbols as absolute. */
4230 if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
4231 sym->st_shndx = SHN_ABS;
4233 return true;
4236 /* Finish up the dynamic sections. */
4238 static bool
4239 loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
4240 asection *sdyn)
4242 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
4243 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
4244 size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
4245 bfd_byte *dyncon, *dynconend;
4247 dynconend = sdyn->contents + sdyn->size;
4248 for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
4250 Elf_Internal_Dyn dyn;
4251 asection *s;
4252 int skipped = 0;
4254 bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
4256 switch (dyn.d_tag)
4258 case DT_PLTGOT:
4259 s = htab->elf.sgotplt;
4260 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
4261 break;
4262 case DT_JMPREL:
4263 s = htab->elf.srelplt;
4264 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
4265 break;
4266 case DT_PLTRELSZ:
4267 s = htab->elf.srelplt;
4268 dyn.d_un.d_val = s->size;
4269 break;
4270 case DT_TEXTREL:
4271 if ((info->flags & DF_TEXTREL) == 0)
4272 skipped = 1;
4273 break;
4274 case DT_FLAGS:
4275 if ((info->flags & DF_TEXTREL) == 0)
4276 dyn.d_un.d_val &= ~DF_TEXTREL;
4277 break;
4279 if (skipped)
4280 skipped_size += dynsize;
4281 else
4282 bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
4284 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
4285 memset (dyncon - skipped_size, 0, skipped_size);
4286 return true;
4289 /* Finish up local dynamic symbol handling. We set the contents of
4290 various dynamic sections here. */
4292 static int
4293 elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
4295 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
4296 struct bfd_link_info *info = (struct bfd_link_info *) inf;
4298 return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
4301 /* Value of struct elf_backend_data->elf_backend_output_arch_local_syms,
4302 this function is called before elf_link_sort_relocs.
4303 So relocation R_LARCH_IRELATIVE for local ifunc can be append to
4304 .rela.dyn (.rela.got) by loongarch_elf_append_rela. */
4306 static bool
4307 elf_loongarch_output_arch_local_syms
4308 (bfd *output_bfd ATTRIBUTE_UNUSED,
4309 struct bfd_link_info *info,
4310 void *flaginfo ATTRIBUTE_UNUSED,
4311 int (*func) (void *, const char *,
4312 Elf_Internal_Sym *,
4313 asection *,
4314 struct elf_link_hash_entry *) ATTRIBUTE_UNUSED)
4316 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
4317 if (htab == NULL)
4318 return false;
4320 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
4321 htab_traverse (htab->loc_hash_table,
4322 elfNN_loongarch_finish_local_dynamic_symbol,
4323 info);
4325 return true;
4328 static bool
4329 loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
4330 struct bfd_link_info *info)
4332 bfd *dynobj;
4333 asection *sdyn, *plt, *gotplt = NULL;
4334 struct loongarch_elf_link_hash_table *htab;
4336 htab = loongarch_elf_hash_table (info);
4337 BFD_ASSERT (htab);
4338 dynobj = htab->elf.dynobj;
4339 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
4341 if (elf_hash_table (info)->dynamic_sections_created)
4343 BFD_ASSERT (htab->elf.splt && sdyn);
4345 if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
4346 return false;
4349 plt = htab->elf.splt;
4350 gotplt = htab->elf.sgotplt;
4352 if (plt && 0 < plt->size)
4354 size_t i;
4355 uint32_t plt_header[PLT_HEADER_INSNS];
4356 if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
4357 plt_header))
4358 return false;
4360 for (i = 0; i < PLT_HEADER_INSNS; i++)
4361 bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
4363 elf_section_data (plt->output_section)->this_hdr.sh_entsize =
4364 PLT_ENTRY_SIZE;
4367 if (htab->elf.sgotplt)
4369 asection *output_section = htab->elf.sgotplt->output_section;
4371 if (bfd_is_abs_section (output_section))
4373 _bfd_error_handler (_("discarded output section: `%pA'"),
4374 htab->elf.sgotplt);
4375 return false;
4378 if (0 < htab->elf.sgotplt->size)
4380 /* Write the first two entries in .got.plt, needed for the dynamic
4381 linker. */
4382 bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
4384 bfd_put_NN (output_bfd, (bfd_vma) 0,
4385 htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
4388 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
4391 if (htab->elf.sgot)
4393 asection *output_section = htab->elf.sgot->output_section;
4395 if (0 < htab->elf.sgot->size)
4397 /* Set the first entry in the global offset table to the address of
4398 the dynamic section. */
4399 bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
4400 bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
4403 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
4406 return true;
4409 /* Return address for Ith PLT stub in section PLT, for relocation REL
4410 or (bfd_vma) -1 if it should not be included. */
4412 static bfd_vma
4413 loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
4414 const arelent *rel ATTRIBUTE_UNUSED)
4416 return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
4419 static enum elf_reloc_type_class
4420 loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
4421 const asection *rel_sec ATTRIBUTE_UNUSED,
4422 const Elf_Internal_Rela *rela)
4424 struct loongarch_elf_link_hash_table *htab;
4425 htab = loongarch_elf_hash_table (info);
4427 if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
4429 /* Check relocation against STT_GNU_IFUNC symbol if there are
4430 dynamic symbols. */
4431 bfd *abfd = info->output_bfd;
4432 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
4433 unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
4434 if (r_symndx != STN_UNDEF)
4436 Elf_Internal_Sym sym;
4437 if (!bed->s->swap_symbol_in (abfd,
4438 htab->elf.dynsym->contents
4439 + r_symndx * bed->s->sizeof_sym,
4440 0, &sym))
4442 /* xgettext:c-format */
4443 _bfd_error_handler (_("%pB symbol number %lu references"
4444 " nonexistent SHT_SYMTAB_SHNDX section"),
4445 abfd, r_symndx);
4446 /* Ideally an error class should be returned here. */
4448 else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
4449 return reloc_class_ifunc;
4453 switch (ELFNN_R_TYPE (rela->r_info))
4455 case R_LARCH_IRELATIVE:
4456 return reloc_class_ifunc;
4457 case R_LARCH_RELATIVE:
4458 return reloc_class_relative;
4459 case R_LARCH_JUMP_SLOT:
4460 return reloc_class_plt;
4461 case R_LARCH_COPY:
4462 return reloc_class_copy;
4463 default:
4464 return reloc_class_normal;
4468 /* Copy the extra info we tack onto an elf_link_hash_entry. */
4470 static void
4471 loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
4472 struct elf_link_hash_entry *dir,
4473 struct elf_link_hash_entry *ind)
4475 struct elf_link_hash_entry *edir, *eind;
4477 edir = dir;
4478 eind = ind;
4480 if (eind->dyn_relocs != NULL)
4482 if (edir->dyn_relocs != NULL)
4484 struct elf_dyn_relocs **pp;
4485 struct elf_dyn_relocs *p;
4487 /* Add reloc counts against the indirect sym to the direct sym
4488 list. Merge any entries against the same section. */
4489 for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
4491 struct elf_dyn_relocs *q;
4493 for (q = edir->dyn_relocs; q != NULL; q = q->next)
4494 if (q->sec == p->sec)
4496 q->pc_count += p->pc_count;
4497 q->count += p->count;
4498 *pp = p->next;
4499 break;
4501 if (q == NULL)
4502 pp = &p->next;
4504 *pp = edir->dyn_relocs;
4507 edir->dyn_relocs = eind->dyn_relocs;
4508 eind->dyn_relocs = NULL;
4511 if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
4513 loongarch_elf_hash_entry(edir)->tls_type
4514 = loongarch_elf_hash_entry(eind)->tls_type;
4515 loongarch_elf_hash_entry(eind)->tls_type = GOT_UNKNOWN;
4517 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
4520 #define PRSTATUS_SIZE 0x1d8
4521 #define PRSTATUS_OFFSET_PR_CURSIG 0xc
4522 #define PRSTATUS_OFFSET_PR_PID 0x20
4523 #define ELF_GREGSET_T_SIZE 0x168
4524 #define PRSTATUS_OFFSET_PR_REG 0x70
4526 /* Support for core dump NOTE sections. */
4528 static bool
4529 loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
4531 switch (note->descsz)
4533 default:
4534 return false;
4536 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
4537 case PRSTATUS_SIZE:
4538 /* pr_cursig */
4539 elf_tdata (abfd)->core->signal =
4540 bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
4542 /* pr_pid */
4543 elf_tdata (abfd)->core->lwpid =
4544 bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
4545 break;
4548 /* Make a ".reg/999" section. */
4549 return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
4550 note->descpos
4551 + PRSTATUS_OFFSET_PR_REG);
4554 #define PRPSINFO_SIZE 0x88
4555 #define PRPSINFO_OFFSET_PR_PID 0x18
4556 #define PRPSINFO_OFFSET_PR_FNAME 0x28
4557 #define PRPSINFO_SIZEOF_PR_FNAME 0x10
4558 #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
4559 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
4561 static bool
4562 loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
4564 switch (note->descsz)
4566 default:
4567 return false;
4569 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
4570 case PRPSINFO_SIZE:
4571 /* pr_pid */
4572 elf_tdata (abfd)->core->pid =
4573 bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
4575 /* pr_fname */
4576 elf_tdata (abfd)->core->program =
4577 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
4578 PRPSINFO_SIZEOF_PR_FNAME);
4580 /* pr_psargs */
4581 elf_tdata (abfd)->core->command =
4582 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
4583 PRPSINFO_SIZEOF_PR_PS_ARGS);
4584 break;
4587 /* Note that for some reason, a spurious space is tacked
4588 onto the end of the args in some (at least one anyway)
4589 implementations, so strip it off if it exists. */
4592 char *command = elf_tdata (abfd)->core->command;
4593 int n = strlen (command);
4595 if (0 < n && command[n - 1] == ' ')
4596 command[n - 1] = '\0';
4599 return true;
4602 /* Set the right mach type. */
4603 static bool
4604 loongarch_elf_object_p (bfd *abfd)
4606 /* There are only two mach types in LoongArch currently. */
4607 if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
4608 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
4609 else
4610 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
4611 return true;
4614 static asection *
4615 loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
4616 Elf_Internal_Rela *rel,
4617 struct elf_link_hash_entry *h,
4618 Elf_Internal_Sym *sym)
4620 if (h != NULL)
4621 switch (ELFNN_R_TYPE (rel->r_info))
4623 case R_LARCH_GNU_VTINHERIT:
4624 case R_LARCH_GNU_VTENTRY:
4625 return NULL;
4628 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
4631 /* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For
4632 executable PLT slots where the executable never takes the address of those
4633 functions, the function symbols are not added to the hash table. */
4635 static bool
4636 elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
4638 if (h->plt.offset != (bfd_vma) -1
4639 && !h->def_regular
4640 && !h->pointer_equality_needed)
4641 return false;
4643 return _bfd_elf_hash_symbol (h);
4646 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
4647 #define TARGET_LITTLE_NAME "elfNN-loongarch"
4648 #define ELF_ARCH bfd_arch_loongarch
4649 #define ELF_TARGET_ID LARCH_ELF_DATA
4650 #define ELF_MACHINE_CODE EM_LOONGARCH
4651 #define ELF_MAXPAGESIZE 0x4000
4652 #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
4653 #define bfd_elfNN_bfd_link_hash_table_create \
4654 loongarch_elf_link_hash_table_create
4655 #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
4656 #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
4657 #define elf_info_to_howto loongarch_info_to_howto_rela
4658 #define bfd_elfNN_bfd_merge_private_bfd_data \
4659 elfNN_loongarch_merge_private_bfd_data
4661 #define elf_backend_reloc_type_class loongarch_reloc_type_class
4662 #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
4663 #define elf_backend_create_dynamic_sections \
4664 loongarch_elf_create_dynamic_sections
4665 #define elf_backend_check_relocs loongarch_elf_check_relocs
4666 #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
4667 #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
4668 #define elf_backend_relocate_section loongarch_elf_relocate_section
4669 #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
4670 #define elf_backend_output_arch_local_syms \
4671 elf_loongarch_output_arch_local_syms
4672 #define elf_backend_finish_dynamic_sections \
4673 loongarch_elf_finish_dynamic_sections
4674 #define elf_backend_object_p loongarch_elf_object_p
4675 #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
4676 #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
4677 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
4678 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
4679 #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
4680 #define bfd_elfNN_bfd_relax_section loongarch_elf_relax_section
4682 #define elf_backend_dtrel_excludes_plt 1
4684 #include "elfNN-target.h"