]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfnn-loongarch.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / elfnn-loongarch.c
CommitLineData
e214f8db 1/* LoongArch-specific support for NN-bit ELF.
d87bef3a 2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
e214f8db 3 Contributed by Loongson Ltd.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
20
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
31static bool
32loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
33 Elf_Internal_Rela *dst)
34{
35 cache_ptr->howto = loongarch_elf_rtype_to_howto (abfd,
36 ELFNN_R_TYPE (dst->r_info));
37 return cache_ptr->howto != NULL;
38}
39
40/* LoongArch ELF linker hash entry. */
41struct loongarch_elf_link_hash_entry
42{
43 struct elf_link_hash_entry elf;
44
e214f8db 45#define GOT_UNKNOWN 0
46#define GOT_NORMAL 1
47#define GOT_TLS_GD 2
48#define GOT_TLS_IE 4
49#define GOT_TLS_LE 8
50 char tls_type;
51};
52
53#define loongarch_elf_hash_entry(ent) \
54 ((struct loongarch_elf_link_hash_entry *) (ent))
55
56struct _bfd_loongarch_elf_obj_tdata
57{
58 struct elf_obj_tdata root;
59
60 /* The tls_type for each local got entry. */
61 char *local_got_tls_type;
62};
63
64#define _bfd_loongarch_elf_tdata(abfd) \
65 ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
66
67#define _bfd_loongarch_elf_local_got_tls_type(abfd) \
68 (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
69
70#define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
71 (*((h) != NULL \
72 ? &loongarch_elf_hash_entry (h)->tls_type \
73 : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
74
75#define is_loongarch_elf(bfd) \
76 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
77 && elf_tdata (bfd) != NULL \
78 && elf_object_id (bfd) == LARCH_ELF_DATA)
79
80struct loongarch_elf_link_hash_table
81{
82 struct elf_link_hash_table elf;
83
84 /* Short-cuts to get to dynamic linker sections. */
85 asection *sdyntdata;
86
87 /* Small local sym to section mapping cache. */
88 struct sym_cache sym_cache;
89
90 /* Used by local STT_GNU_IFUNC symbols. */
91 htab_t loc_hash_table;
92 void *loc_hash_memory;
93
94 /* The max alignment of output sections. */
95 bfd_vma max_alignment;
96};
97
98/* Get the LoongArch ELF linker hash table from a link_info structure. */
99#define loongarch_elf_hash_table(p) \
100 (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
101 ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
102 : NULL)
103
104#define MINUS_ONE ((bfd_vma) 0 - 1)
105
106#define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
107
108#define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
109#define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
110
111#define PLT_HEADER_INSNS 8
112#define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
113
114#define PLT_ENTRY_INSNS 4
115#define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
116
117#define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
118
119#define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
120
121#define elf_backend_want_got_plt 1
122
123#define elf_backend_plt_readonly 1
124
6d13722a 125#define elf_backend_want_plt_sym 1
e214f8db 126#define elf_backend_plt_alignment 4
127#define elf_backend_can_gc_sections 1
6d13722a 128#define elf_backend_can_refcount 1
e214f8db 129#define elf_backend_want_got_sym 1
130
131#define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
132
133#define elf_backend_want_dynrelro 1
6d13722a 134#define elf_backend_rela_normal 1
48ca1b26 135#define elf_backend_default_execstack 0
e214f8db 136
137/* Generate a PLT header. */
138
139static bool
140loongarch_make_plt_header (bfd_vma got_plt_addr, bfd_vma plt_header_addr,
141 uint32_t *entry)
142{
143 bfd_vma pcrel = got_plt_addr - plt_header_addr;
144 bfd_vma hi, lo;
145
146 if (pcrel + 0x80000800 > 0xffffffff)
147 {
148 _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
149 bfd_set_error (bfd_error_bad_value);
150 return false;
151 }
152 hi = ((pcrel + 0x800) >> 12) & 0xfffff;
153 lo = pcrel & 0xfff;
154
155 /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
156 sub.[wd] $t1, $t1, $t3
157 ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
158 addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
159 addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
160 srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
161 ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
162 jirl $r0, $t3, 0 */
163
164 if (GOT_ENTRY_SIZE == 8)
165 {
166 entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
167 entry[1] = 0x0011bdad;
168 entry[2] = 0x28c001cf | (lo & 0xfff) << 10;
169 entry[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
170 entry[4] = 0x02c001cc | (lo & 0xfff) << 10;
171 entry[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
172 entry[6] = 0x28c0018c | GOT_ENTRY_SIZE << 10;
173 entry[7] = 0x4c0001e0;
174 }
175 else
176 {
177 entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
178 entry[1] = 0x00113dad;
179 entry[2] = 0x288001cf | (lo & 0xfff) << 10;
180 entry[3] = 0x028001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
181 entry[4] = 0x028001cc | (lo & 0xfff) << 10;
182 entry[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
183 entry[6] = 0x2880018c | GOT_ENTRY_SIZE << 10;
184 entry[7] = 0x4c0001e0;
185 }
186 return true;
187}
188
189/* Generate a PLT entry. */
190
191static bool
192loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, bfd_vma plt_entry_addr,
193 uint32_t *entry)
194{
195 bfd_vma pcrel = got_plt_entry_addr - plt_entry_addr;
196 bfd_vma hi, lo;
197
198 if (pcrel + 0x80000800 > 0xffffffff)
199 {
200 _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
201 bfd_set_error (bfd_error_bad_value);
202 return false;
203 }
204 hi = ((pcrel + 0x800) >> 12) & 0xfffff;
205 lo = pcrel & 0xfff;
206
207 entry[0] = 0x1c00000f | (hi & 0xfffff) << 5;
208 entry[1] = ((GOT_ENTRY_SIZE == 8 ? 0x28c001ef : 0x288001ef)
209 | (lo & 0xfff) << 10);
210 entry[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
211 entry[3] = 0x03400000; /* nop */
212
213 return true;
214}
215
216/* Create an entry in an LoongArch ELF linker hash table. */
217
218static struct bfd_hash_entry *
219link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
220 const char *string)
221{
222 struct loongarch_elf_link_hash_entry *eh;
223
224 /* Allocate the structure if it has not already been allocated by a
225 subclass. */
226 if (entry == NULL)
227 {
228 entry = bfd_hash_allocate (table, sizeof (*eh));
229 if (entry == NULL)
230 return entry;
231 }
232
233 /* Call the allocation method of the superclass. */
234 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
235 if (entry != NULL)
236 {
237 eh = (struct loongarch_elf_link_hash_entry *) entry;
e214f8db 238 eh->tls_type = GOT_UNKNOWN;
239 }
240
241 return entry;
242}
243
244/* Compute a hash of a local hash entry. We use elf_link_hash_entry
245 for local symbol so that we can handle local STT_GNU_IFUNC symbols
246 as global symbol. We reuse indx and dynstr_index for local symbol
247 hash since they aren't used by global symbols in this backend. */
248
249static hashval_t
250elfNN_loongarch_local_htab_hash (const void *ptr)
251{
252 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr;
253 return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
254}
255
256/* Compare local hash entries. */
257
258static int
259elfNN_loongarch_local_htab_eq (const void *ptr1, const void *ptr2)
260{
261 struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1;
262 struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2;
263
264 return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
265}
266
267/* Find and/or create a hash entry for local symbol. */
268static struct elf_link_hash_entry *
269elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table *htab,
270 bfd *abfd, const Elf_Internal_Rela *rel,
271 bool create)
272{
273 struct loongarch_elf_link_hash_entry e, *ret;
274 asection *sec = abfd->sections;
275 hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, ELFNN_R_SYM (rel->r_info));
276 void **slot;
277
278 e.elf.indx = sec->id;
279 e.elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
280 slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
281 create ? INSERT : NO_INSERT);
282
283 if (!slot)
284 return NULL;
285
286 if (*slot)
287 {
288 ret = (struct loongarch_elf_link_hash_entry *) *slot;
289 return &ret->elf;
290 }
291
292 ret = ((struct loongarch_elf_link_hash_entry *)
293 objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
294 sizeof (struct loongarch_elf_link_hash_entry)));
295 if (ret)
296 {
297 memset (ret, 0, sizeof (*ret));
298 ret->elf.indx = sec->id;
299 ret->elf.pointer_equality_needed = 0;
300 ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
301 ret->elf.dynindx = -1;
302 ret->elf.needs_plt = 0;
303 ret->elf.plt.refcount = -1;
304 ret->elf.got.refcount = -1;
305 ret->elf.def_dynamic = 0;
306 ret->elf.def_regular = 1;
307 ret->elf.ref_dynamic = 0; /* This should be always 0 for local. */
308 ret->elf.ref_regular = 0;
309 ret->elf.forced_local = 1;
310 ret->elf.root.type = bfd_link_hash_defined;
311 *slot = ret;
312 }
313 return &ret->elf;
314}
315
316/* Destroy an LoongArch elf linker hash table. */
317
318static void
319elfNN_loongarch_link_hash_table_free (bfd *obfd)
320{
321 struct loongarch_elf_link_hash_table *ret;
322 ret = (struct loongarch_elf_link_hash_table *) obfd->link.hash;
323
324 if (ret->loc_hash_table)
325 htab_delete (ret->loc_hash_table);
326 if (ret->loc_hash_memory)
327 objalloc_free ((struct objalloc *) ret->loc_hash_memory);
328
329 _bfd_elf_link_hash_table_free (obfd);
330}
331
332/* Create a LoongArch ELF linker hash table. */
333
334static struct bfd_link_hash_table *
335loongarch_elf_link_hash_table_create (bfd *abfd)
336{
337 struct loongarch_elf_link_hash_table *ret;
338 bfd_size_type amt = sizeof (struct loongarch_elf_link_hash_table);
339
340 ret = (struct loongarch_elf_link_hash_table *) bfd_zmalloc (amt);
341 if (ret == NULL)
342 return NULL;
343
344 if (!_bfd_elf_link_hash_table_init
345 (&ret->elf, abfd, link_hash_newfunc,
346 sizeof (struct loongarch_elf_link_hash_entry), LARCH_ELF_DATA))
347 {
348 free (ret);
349 return NULL;
350 }
351
352 ret->max_alignment = MINUS_ONE;
353
354 ret->loc_hash_table = htab_try_create (1024, elfNN_loongarch_local_htab_hash,
355 elfNN_loongarch_local_htab_eq, NULL);
356 ret->loc_hash_memory = objalloc_create ();
357 if (!ret->loc_hash_table || !ret->loc_hash_memory)
358 {
359 elfNN_loongarch_link_hash_table_free (abfd);
360 return NULL;
361 }
362 ret->elf.root.hash_table_free = elfNN_loongarch_link_hash_table_free;
363
364 return &ret->elf.root;
365}
366
367/* Merge backend specific data from an object file to the output
368 object file when linking. */
369
370static bool
371elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
372{
373 bfd *obfd = info->output_bfd;
374 flagword in_flags = elf_elfheader (ibfd)->e_flags;
375 flagword out_flags = elf_elfheader (obfd)->e_flags;
376
377 if (!is_loongarch_elf (ibfd) || !is_loongarch_elf (obfd))
378 return true;
379
380 if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
381 {
382 _bfd_error_handler (_("%pB: ABI is incompatible with that of "
383 "the selected emulation:\n"
384 " target emulation `%s' does not match `%s'"),
385 ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
386 return false;
387 }
388
389 if (!_bfd_elf_merge_object_attributes (ibfd, info))
390 return false;
391
83c5f3ae
XR
392 /* If the input BFD is not a dynamic object and it does not contain any
393 non-data sections, do not account its ABI. For example, various
394 packages produces such data-only relocatable objects with
395 `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
396 But they are compatible with all ABIs. */
397 if (!(ibfd->flags & DYNAMIC))
398 {
399 asection *sec;
400 bool have_code_sections = false;
401 for (sec = ibfd->sections; sec != NULL; sec = sec->next)
402 if ((bfd_section_flags (sec)
403 & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
404 == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
405 {
406 have_code_sections = true;
407 break;
408 }
409 if (!have_code_sections)
410 return true;
411 }
412
e214f8db 413 if (!elf_flags_init (obfd))
414 {
415 elf_flags_init (obfd) = true;
416 elf_elfheader (obfd)->e_flags = in_flags;
417 return true;
418 }
c4a7e6b5 419 else if (out_flags != in_flags)
420 {
421 if ((EF_LOONGARCH_IS_OBJ_V0 (out_flags)
422 && EF_LOONGARCH_IS_OBJ_V1 (in_flags))
423 || (EF_LOONGARCH_IS_OBJ_V0 (in_flags)
424 && EF_LOONGARCH_IS_OBJ_V1 (out_flags)))
425 {
426 elf_elfheader (obfd)->e_flags |= EF_LOONGARCH_OBJABI_V1;
427 out_flags = elf_elfheader (obfd)->e_flags;
428 in_flags = out_flags;
429 }
430 }
e214f8db 431
432 /* Disallow linking different ABIs. */
c4a7e6b5 433 /* Only check relocation version.
434 The obj_v0 is compatible with obj_v1. */
3b14682a 435 if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
e214f8db 436 {
437 _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd);
438 goto fail;
439 }
440
441 return true;
442
443 fail:
444 bfd_set_error (bfd_error_bad_value);
445 return false;
446}
447
448/* Create the .got section. */
449
450static bool
451loongarch_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
452{
453 flagword flags;
454 char *name;
455 asection *s, *s_got;
456 struct elf_link_hash_entry *h;
457 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
458 struct elf_link_hash_table *htab = elf_hash_table (info);
459
460 /* This function may be called more than once. */
461 if (htab->sgot != NULL)
462 return true;
463
464 flags = bed->dynamic_sec_flags;
465 name = bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got";
466 s = bfd_make_section_anyway_with_flags (abfd, name, flags | SEC_READONLY);
467
468 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
469 return false;
470 htab->srelgot = s;
471
472 s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
473 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
474 return false;
475 htab->sgot = s;
476
477 /* The first bit of the global offset table is the header. */
478 s->size += bed->got_header_size;
479
480 if (bed->want_got_plt)
481 {
482 s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
483 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
484 return false;
485 htab->sgotplt = s;
486
487 /* Reserve room for the header. */
488 s->size = GOTPLT_HEADER_SIZE;
489 }
490
491 if (bed->want_got_sym)
492 {
493 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
494 section. We don't do this in the linker script because we don't want
495 to define the symbol if we are not creating a global offset table. */
496 h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
497 "_GLOBAL_OFFSET_TABLE_");
498 elf_hash_table (info)->hgot = h;
499 if (h == NULL)
500 return false;
501 }
502 return true;
503}
504
505/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
506 .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
507 hash table. */
508
509static bool
510loongarch_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
511{
512 struct loongarch_elf_link_hash_table *htab;
513
514 htab = loongarch_elf_hash_table (info);
515 BFD_ASSERT (htab != NULL);
516
517 if (!loongarch_elf_create_got_section (dynobj, info))
518 return false;
519
520 if (!_bfd_elf_create_dynamic_sections (dynobj, info))
521 return false;
522
523 if (!bfd_link_pic (info))
524 htab->sdyntdata
525 = bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
526 SEC_ALLOC | SEC_THREAD_LOCAL);
527
528 if (!htab->elf.splt || !htab->elf.srelplt || !htab->elf.sdynbss
529 || (!bfd_link_pic (info) && (!htab->elf.srelbss || !htab->sdyntdata)))
530 abort ();
531
532 return true;
533}
534
535static bool
536loongarch_elf_record_tls_and_got_reference (bfd *abfd,
537 struct bfd_link_info *info,
538 struct elf_link_hash_entry *h,
539 unsigned long symndx,
540 char tls_type)
541{
542 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
543 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
544
545 /* This is a global offset table entry for a local symbol. */
546 if (elf_local_got_refcounts (abfd) == NULL)
547 {
548 bfd_size_type size =
549 symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (tls_type));
550 if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
551 return false;
552 _bfd_loongarch_elf_local_got_tls_type (abfd) =
553 (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
554 }
555
556 switch (tls_type)
557 {
558 case GOT_NORMAL:
559 case GOT_TLS_GD:
560 case GOT_TLS_IE:
561 /* Need GOT. */
562 if (htab->elf.sgot == NULL
563 && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
564 return false;
565 if (h)
566 {
567 if (h->got.refcount < 0)
568 h->got.refcount = 0;
569 h->got.refcount++;
570 }
571 else
572 elf_local_got_refcounts (abfd)[symndx]++;
573 break;
574 case GOT_TLS_LE:
575 /* No need for GOT. */
576 break;
577 default:
578 _bfd_error_handler (_("Internal error: unreachable."));
579 return false;
580 }
581
582 char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
583 *new_tls_type |= tls_type;
584 if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
585 {
586 _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
587 "thread local symbol"),
588 abfd,
589 h ? h->root.root.string : "<local>");
590 return false;
591 }
592
593 return true;
594}
595
596/* Look through the relocs for a section during the first phase, and
597 allocate space in the global offset table or procedure linkage
598 table. */
599
600static bool
601loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
602 asection *sec, const Elf_Internal_Rela *relocs)
603{
604 struct loongarch_elf_link_hash_table *htab;
605 Elf_Internal_Shdr *symtab_hdr;
606 struct elf_link_hash_entry **sym_hashes;
607 const Elf_Internal_Rela *rel;
608 asection *sreloc = NULL;
609
610 if (bfd_link_relocatable (info))
611 return true;
612
613 htab = loongarch_elf_hash_table (info);
614 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
615 sym_hashes = elf_sym_hashes (abfd);
616
617 if (htab->elf.dynobj == NULL)
618 htab->elf.dynobj = abfd;
619
620 for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
621 {
622 unsigned int r_type;
623 unsigned int r_symndx;
624 struct elf_link_hash_entry *h;
625 Elf_Internal_Sym *isym = NULL;
626
e214f8db 627 r_symndx = ELFNN_R_SYM (rel->r_info);
628 r_type = ELFNN_R_TYPE (rel->r_info);
629
630 if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
631 {
632 _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx);
633 return false;
634 }
635
636 if (r_symndx < symtab_hdr->sh_info)
637 {
638 /* A local symbol. */
6d13722a 639 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
e214f8db 640 if (isym == NULL)
641 return false;
642
643 if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
644 {
645 h = elfNN_loongarch_get_local_sym_hash (htab, abfd, rel, true);
646 if (h == NULL)
647 return false;
648
649 h->type = STT_GNU_IFUNC;
650 h->ref_regular = 1;
651 }
652 else
653 h = NULL;
654 }
655 else
656 {
657 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
658 while (h->root.type == bfd_link_hash_indirect
659 || h->root.type == bfd_link_hash_warning)
660 h = (struct elf_link_hash_entry *) h->root.u.i.link;
661 }
662
d218dba3 663 /* It is referenced by a non-shared object. */
664 if (h != NULL)
665 h->ref_regular = 1;
666
e214f8db 667 if (h && h->type == STT_GNU_IFUNC)
668 {
669 if (htab->elf.dynobj == NULL)
670 htab->elf.dynobj = abfd;
671
6d13722a 672 /* Create 'irelifunc' in PIC object. */
673 if (bfd_link_pic (info)
674 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
675 return false;
676 /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
677 else if (!htab->elf.splt
678 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
679 return false;
d218dba3 680 /* Create the ifunc sections, iplt and ipltgot, for static
681 executables. */
682 if ((r_type == R_LARCH_64 || r_type == R_LARCH_32)
683 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
684 return false;
685
e214f8db 686 if (h->plt.refcount < 0)
687 h->plt.refcount = 0;
688 h->plt.refcount++;
689 h->needs_plt = 1;
690
691 elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
692 }
693
6d13722a 694 int need_dynreloc = 0;
695 int only_need_pcrel = 0;
696
e214f8db 697 switch (r_type)
698 {
6d13722a 699 case R_LARCH_GOT_PC_HI20:
700 case R_LARCH_GOT_HI20:
e214f8db 701 case R_LARCH_SOP_PUSH_GPREL:
6d13722a 702 /* For la.global. */
703 if (h)
704 h->pointer_equality_needed = 1;
e214f8db 705 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
706 r_symndx,
707 GOT_NORMAL))
708 return false;
709 break;
710
6d13722a 711 case R_LARCH_TLS_LD_PC_HI20:
712 case R_LARCH_TLS_LD_HI20:
713 case R_LARCH_TLS_GD_PC_HI20:
714 case R_LARCH_TLS_GD_HI20:
e214f8db 715 case R_LARCH_SOP_PUSH_TLS_GD:
716 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
717 r_symndx,
718 GOT_TLS_GD))
719 return false;
720 break;
721
6d13722a 722 case R_LARCH_TLS_IE_PC_HI20:
723 case R_LARCH_TLS_IE_HI20:
e214f8db 724 case R_LARCH_SOP_PUSH_TLS_GOT:
725 if (bfd_link_pic (info))
726 /* May fail for lazy-bind. */
727 info->flags |= DF_STATIC_TLS;
728
729 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
730 r_symndx,
731 GOT_TLS_IE))
732 return false;
733 break;
734
6d13722a 735 case R_LARCH_TLS_LE_HI20:
e214f8db 736 case R_LARCH_SOP_PUSH_TLS_TPREL:
737 if (!bfd_link_executable (info))
738 return false;
739
740 info->flags |= DF_STATIC_TLS;
741
742 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
743 r_symndx,
744 GOT_TLS_LE))
745 return false;
746 break;
747
6d13722a 748 case R_LARCH_ABS_HI20:
e214f8db 749 case R_LARCH_SOP_PUSH_ABSOLUTE:
750 if (h != NULL)
751 /* If this reloc is in a read-only section, we might
752 need a copy reloc. We can't check reliably at this
753 stage whether the section is read-only, as input
754 sections have not yet been mapped to output sections.
755 Tentatively set the flag for now, and correct in
756 adjust_dynamic_symbol. */
757 h->non_got_ref = 1;
758 break;
759
6d13722a 760 case R_LARCH_PCALA_HI20:
e214f8db 761 if (h != NULL)
762 {
42bd5254 763 /* For pcalau12i + jirl. */
764 h->needs_plt = 1;
765 if (h->plt.refcount < 0)
766 h->plt.refcount = 0;
767 h->plt.refcount++;
768
e214f8db 769 h->non_got_ref = 1;
6d13722a 770 h->pointer_equality_needed = 1;
771 }
772
773 break;
774
775 case R_LARCH_B21:
776 case R_LARCH_B16:
777 case R_LARCH_B26:
778 if (h != NULL)
779 {
780 h->needs_plt = 1;
781 if (!bfd_link_pic (info))
782 h->non_got_ref = 1;
e214f8db 783
784 /* We try to create PLT stub for all non-local function. */
785 if (h->plt.refcount < 0)
786 h->plt.refcount = 0;
787 h->plt.refcount++;
788 }
6d13722a 789
790 break;
791
792 case R_LARCH_SOP_PUSH_PCREL:
793 if (h != NULL)
794 {
795 if (!bfd_link_pic (info))
796 h->non_got_ref = 1;
797
798 /* We try to create PLT stub for all non-local function. */
799 if (h->plt.refcount < 0)
800 h->plt.refcount = 0;
801 h->plt.refcount++;
802 h->pointer_equality_needed = 1;
803 }
804
e214f8db 805 break;
806
807 case R_LARCH_SOP_PUSH_PLT_PCREL:
808 /* This symbol requires a procedure linkage table entry. We
809 actually build the entry in adjust_dynamic_symbol,
810 because this might be a case of linking PIC code without
811 linking in any dynamic objects, in which case we don't
812 need to generate a procedure linkage table after all. */
813 if (h != NULL)
814 {
815 h->needs_plt = 1;
816 if (h->plt.refcount < 0)
817 h->plt.refcount = 0;
818 h->plt.refcount++;
819 }
820 break;
821
822 case R_LARCH_TLS_DTPREL32:
823 case R_LARCH_TLS_DTPREL64:
824 need_dynreloc = 1;
825 only_need_pcrel = 1;
826 break;
827
828 case R_LARCH_JUMP_SLOT:
829 case R_LARCH_32:
830 case R_LARCH_64:
6d13722a 831
e214f8db 832 need_dynreloc = 1;
833
834 /* If resolved symbol is defined in this object,
835 1. Under pie, the symbol is known. We convert it
836 into R_LARCH_RELATIVE and need load-addr still.
837 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
838 3. Under dll, R_LARCH_NN can't be changed normally, since
839 its defination could be covered by the one in executable.
840 For symbolic, we convert it into R_LARCH_RELATIVE.
841 Thus, only under pde, it needs pcrel only. We discard it. */
842 only_need_pcrel = bfd_link_pde (info);
843
d218dba3 844 if (h != NULL
845 && (!bfd_link_pic (info)
846 || h->type == STT_GNU_IFUNC))
847 {
848 /* This reloc might not bind locally. */
849 h->non_got_ref = 1;
850 h->pointer_equality_needed = 1;
851
852 if (!h->def_regular
853 || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
854 {
855 /* We may need a .plt entry if the symbol is a function
856 defined in a shared lib or is a function referenced
857 from the code or read-only section. */
858 h->plt.refcount += 1;
859 }
860 }
e214f8db 861 break;
862
863 case R_LARCH_GNU_VTINHERIT:
864 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
865 return false;
866 break;
867
868 case R_LARCH_GNU_VTENTRY:
869 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
870 return false;
871 break;
872
873 default:
874 break;
875 }
876
877 /* Record some info for sizing and allocating dynamic entry. */
878 if (need_dynreloc && (sec->flags & SEC_ALLOC))
879 {
880 /* When creating a shared object, we must copy these
881 relocs into the output file. We create a reloc
882 section in dynobj and make room for the reloc. */
883 struct elf_dyn_relocs *p;
884 struct elf_dyn_relocs **head;
885
886 if (sreloc == NULL)
887 {
888 sreloc
889 = _bfd_elf_make_dynamic_reloc_section (sec, htab->elf.dynobj,
890 LARCH_ELF_LOG_WORD_BYTES,
891 abfd, /*rela?*/ true);
892 if (sreloc == NULL)
893 return false;
894 }
895
896 /* If this is a global symbol, we count the number of
897 relocations we need for this symbol. */
898 if (h != NULL)
d218dba3 899 head = &h->dyn_relocs;
e214f8db 900 else
901 {
902 /* Track dynamic relocs needed for local syms too.
903 We really need local syms available to do this
904 easily. Oh well. */
905
906 asection *s;
907 void *vpp;
908
909 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
910 if (s == NULL)
911 s = sec;
912
913 vpp = &elf_section_data (s)->local_dynrel;
914 head = (struct elf_dyn_relocs **) vpp;
915 }
916
917 p = *head;
918 if (p == NULL || p->sec != sec)
919 {
920 bfd_size_type amt = sizeof *p;
921 p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt);
922 if (p == NULL)
923 return false;
924 p->next = *head;
925 *head = p;
926 p->sec = sec;
927 p->count = 0;
928 p->pc_count = 0;
929 }
930
931 p->count++;
932 p->pc_count += only_need_pcrel;
933 }
934 }
935
936 return true;
937}
938
939/* Find dynamic relocs for H that apply to read-only sections. */
940
941static asection *
942readonly_dynrelocs (struct elf_link_hash_entry *h)
943{
944 struct elf_dyn_relocs *p;
945
d218dba3 946 for (p = h->dyn_relocs; p != NULL; p = p->next)
e214f8db 947 {
948 asection *s = p->sec->output_section;
949
950 if (s != NULL && (s->flags & SEC_READONLY) != 0)
951 return p->sec;
952 }
953 return NULL;
954}
955
956/* Adjust a symbol defined by a dynamic object and referenced by a
957 regular object. The current definition is in some section of the
958 dynamic object, but we're not including those sections. We have to
959 change the definition to something the rest of the link can
960 understand. */
961static bool
962loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
963 struct elf_link_hash_entry *h)
964{
965 struct loongarch_elf_link_hash_table *htab;
e214f8db 966 bfd *dynobj;
e214f8db 967
968 htab = loongarch_elf_hash_table (info);
969 BFD_ASSERT (htab != NULL);
970
971 dynobj = htab->elf.dynobj;
972
973 /* Make sure we know what is going on here. */
974 BFD_ASSERT (dynobj != NULL
975 && (h->needs_plt || h->type == STT_GNU_IFUNC || h->is_weakalias
976 || (h->def_dynamic && h->ref_regular && !h->def_regular)));
977
978 /* If this is a function, put it in the procedure linkage table. We
979 will fill in the contents of the procedure linkage table later
980 (although we could actually do it here). */
981 if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
982 {
983 if (h->plt.refcount < 0
984 || (h->type != STT_GNU_IFUNC
985 && (SYMBOL_REFERENCES_LOCAL (info, h)
986 || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
987 && h->root.type == bfd_link_hash_undefweak))))
988 {
989 /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
990 in an input file, but the symbol was never referred to by a
991 dynamic object, or if all references were garbage collected.
992 In such a case, we don't actually need to build a PLT entry. */
993 h->plt.offset = MINUS_ONE;
994 h->needs_plt = 0;
995 }
996 else
997 h->needs_plt = 1;
998
999 return true;
1000 }
1001 else
1002 h->plt.offset = MINUS_ONE;
1003
1004 /* If this is a weak symbol, and there is a real definition, the
1005 processor independent code will have arranged for us to see the
1006 real definition first, and we can just use the same value. */
1007 if (h->is_weakalias)
1008 {
1009 struct elf_link_hash_entry *def = weakdef (h);
1010 BFD_ASSERT (def->root.type == bfd_link_hash_defined);
1011 h->root.u.def.section = def->root.u.def.section;
1012 h->root.u.def.value = def->root.u.def.value;
1013 return true;
1014 }
1015
6d13722a 1016 /* R_LARCH_COPY is not adept glibc, not to generate. */
1017 /* Can not print anything, because make check ld. */
1018 return true;
e214f8db 1019}
1020
1021/* Allocate space in .plt, .got and associated reloc sections for
1022 dynamic relocs. */
1023
1024static bool
1025allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
1026{
1027 struct bfd_link_info *info;
1028 struct loongarch_elf_link_hash_table *htab;
e214f8db 1029 struct elf_dyn_relocs *p;
1030
1031 if (h->root.type == bfd_link_hash_indirect)
1032 return true;
1033
d218dba3 1034 if (h->type == STT_GNU_IFUNC
1035 && h->def_regular)
1036 return true;
1037
e214f8db 1038 info = (struct bfd_link_info *) inf;
1039 htab = loongarch_elf_hash_table (info);
6d13722a 1040 bool dyn = htab->elf.dynamic_sections_created;
e214f8db 1041 BFD_ASSERT (htab != NULL);
1042
1043 do
1044 {
1045 asection *plt, *gotplt, *relplt;
1046
1047 if (!h->needs_plt)
1048 break;
1049
1050 h->needs_plt = 0;
1051
1052 if (htab->elf.splt)
1053 {
6d13722a 1054 if (h->dynindx == -1 && !h->forced_local && dyn
1055 && h->root.type == bfd_link_hash_undefweak)
1056 {
1057 if (!bfd_elf_link_record_dynamic_symbol (info, h))
1058 return false;
1059 }
e214f8db 1060
1061 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
1062 && h->type != STT_GNU_IFUNC)
1063 break;
1064
1065 plt = htab->elf.splt;
1066 gotplt = htab->elf.sgotplt;
1067 relplt = htab->elf.srelplt;
1068 }
1069 else if (htab->elf.iplt)
1070 {
1071 /* .iplt only for IFUNC. */
1072 if (h->type != STT_GNU_IFUNC)
1073 break;
1074
1075 plt = htab->elf.iplt;
1076 gotplt = htab->elf.igotplt;
1077 relplt = htab->elf.irelplt;
1078 }
1079 else
1080 break;
1081
1082 if (plt->size == 0)
1083 plt->size = PLT_HEADER_SIZE;
1084
1085 h->plt.offset = plt->size;
1086 plt->size += PLT_ENTRY_SIZE;
1087 gotplt->size += GOT_ENTRY_SIZE;
1088 relplt->size += sizeof (ElfNN_External_Rela);
1089
d218dba3 1090 /* If this symbol is not defined in a regular file, and we are
1091 not generating a shared library, then set the symbol to this
1092 location in the .plt. This is required to make function
1093 pointers compare as equal between the normal executable and
1094 the shared library. */
6d13722a 1095 if (!bfd_link_pic (info)
d218dba3 1096 && !h->def_regular)
1097 {
1098 h->root.u.def.section = plt;
1099 h->root.u.def.value = h->plt.offset;
1100 }
1101
e214f8db 1102 h->needs_plt = 1;
1103 }
1104 while (0);
1105
1106 if (!h->needs_plt)
1107 h->plt.offset = MINUS_ONE;
1108
1109 if (0 < h->got.refcount)
1110 {
1111 asection *s;
e214f8db 1112 int tls_type = loongarch_elf_hash_entry (h)->tls_type;
1113
1114 /* Make sure this symbol is output as a dynamic symbol.
1115 Undefined weak syms won't yet be marked as dynamic. */
6d13722a 1116 if (h->dynindx == -1 && !h->forced_local && dyn
1117 && h->root.type == bfd_link_hash_undefweak)
d218dba3 1118 {
6d13722a 1119 if (!bfd_elf_link_record_dynamic_symbol (info, h))
1120 return false;
d218dba3 1121 }
e214f8db 1122
1123 s = htab->elf.sgot;
1124 h->got.offset = s->size;
e214f8db 1125 if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
1126 {
1127 /* TLS_GD needs two dynamic relocs and two GOT slots. */
1128 if (tls_type & GOT_TLS_GD)
1129 {
1130 s->size += 2 * GOT_ENTRY_SIZE;
6d13722a 1131 if (bfd_link_executable (info))
1132 {
1133 /* Link exe and not defined local. */
1134 if (!SYMBOL_REFERENCES_LOCAL (info, h))
1135 htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1136 }
1137 else
1138 {
1139 if (SYMBOL_REFERENCES_LOCAL (info, h))
1140 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1141 else
1142 htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1143 }
e214f8db 1144 }
1145
1146 /* TLS_IE needs one dynamic reloc and one GOT slot. */
1147 if (tls_type & GOT_TLS_IE)
1148 {
1149 s->size += GOT_ENTRY_SIZE;
6d13722a 1150
1151 if (bfd_link_executable (info))
1152 {
1153 /* Link exe and not defined local. */
1154 if (!SYMBOL_REFERENCES_LOCAL (info, h))
1155 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1156 }
1157 else
1158 {
1159 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1160 }
e214f8db 1161 }
1162 }
1163 else
1164 {
1165 s->size += GOT_ENTRY_SIZE;
6d13722a 1166 if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1167 || h->root.type != bfd_link_hash_undefweak)
1168 && (bfd_link_pic (info)
1169 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
1170 h))
1171 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
1172 /* Undefined weak symbol in static PIE resolves to 0 without
1173 any dynamic relocations. */
e214f8db 1174 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1175 }
1176 }
1177 else
1178 h->got.offset = MINUS_ONE;
1179
d218dba3 1180 if (h->dyn_relocs == NULL)
e214f8db 1181 return true;
1182
6d13722a 1183 /* Extra dynamic relocate,
1184 * R_LARCH_64
1185 * R_LARCH_TLS_DTPRELNN
1186 * R_LARCH_JUMP_SLOT
1187 * R_LARCH_NN. */
1188
1189 if (SYMBOL_CALLS_LOCAL (info, h))
e214f8db 1190 {
1191 struct elf_dyn_relocs **pp;
1192
d218dba3 1193 for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
e214f8db 1194 {
1195 p->count -= p->pc_count;
1196 p->pc_count = 0;
1197 if (p->count == 0)
1198 *pp = p->next;
1199 else
1200 pp = &p->next;
1201 }
1202 }
1203
1204 if (h->root.type == bfd_link_hash_undefweak)
1205 {
6d13722a 1206 if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
1207 || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
1208 || (!bfd_link_pic (info) && h->non_got_ref))
d218dba3 1209 h->dyn_relocs = NULL;
6d13722a 1210 else if (h->dynindx == -1 && !h->forced_local)
1211 {
1212 /* Make sure this symbol is output as a dynamic symbol.
1213 Undefined weak syms won't yet be marked as dynamic. */
1214 if (!bfd_elf_link_record_dynamic_symbol (info, h))
1215 return false;
1216
1217 if (h->dynindx == -1)
1218 h->dyn_relocs = NULL;
1219 }
e214f8db 1220 }
1221
d218dba3 1222 for (p = h->dyn_relocs; p != NULL; p = p->next)
e214f8db 1223 {
1224 asection *sreloc = elf_section_data (p->sec)->sreloc;
1225 sreloc->size += p->count * sizeof (ElfNN_External_Rela);
1226 }
1227
1228 return true;
1229}
1230
bc2a35c0 1231/* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
1232 For local def and ref ifunc,
1233 dynamic relocations are stored in
1234 1. rela.srelgot section in dynamic object (dll or exec).
1235 2. rela.irelplt section in static executable.
1236 Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
1237 instead of rela.srelplt. Glibc ELF loader will not support
1238 R_LARCH_IRELATIVE relocation in rela.plt. */
1239
1240static bool
1241local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
1242 struct elf_link_hash_entry *h,
1243 struct elf_dyn_relocs **head,
1244 unsigned int plt_entry_size,
1245 unsigned int plt_header_size,
1246 unsigned int got_entry_size,
1247 bool avoid_plt)
1248{
1249 asection *plt, *gotplt, *relplt;
1250 struct elf_dyn_relocs *p;
1251 unsigned int sizeof_reloc;
1252 const struct elf_backend_data *bed;
1253 struct elf_link_hash_table *htab;
1254 /* If AVOID_PLT is TRUE, don't use PLT if possible. */
1255 bool use_plt = !avoid_plt || h->plt.refcount > 0;
1256 bool need_dynreloc = !use_plt || bfd_link_pic (info);
1257
1258 /* When a PIC object references a STT_GNU_IFUNC symbol defined
1259 in executable or it isn't referenced via PLT, the address of
1260 the resolved function may be used. But in non-PIC executable,
1261 the address of its plt slot may be used. Pointer equality may
1262 not work correctly. PIE or non-PLT reference should be used if
1263 pointer equality is required here.
1264
1265 If STT_GNU_IFUNC symbol is defined in position-dependent executable,
1266 backend should change it to the normal function and set its address
1267 to its PLT entry which should be resolved by R_*_IRELATIVE at
1268 run-time. All external references should be resolved to its PLT in
1269 executable. */
1270 if (!need_dynreloc
1271 && !(bfd_link_pde (info) && h->def_regular)
1272 && (h->dynindx != -1
1273 || info->export_dynamic)
1274 && h->pointer_equality_needed)
1275 {
1276 info->callbacks->einfo
1277 /* xgettext:c-format. */
1278 (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
1279 "equality in `%pB' can not be used when making an "
1280 "executable; recompile with -fPIE and relink with -pie\n"),
1281 h->root.root.string,
1282 h->root.u.def.section->owner);
1283 bfd_set_error (bfd_error_bad_value);
1284 return false;
1285 }
1286
1287 htab = elf_hash_table (info);
1288
1289 /* When the symbol is marked with regular reference, if PLT isn't used
1290 or we are building a PIC object, we must keep dynamic relocation
1291 if there is non-GOT reference and use PLT if there is PC-relative
1292 reference. */
1293 if (need_dynreloc && h->ref_regular)
1294 {
1295 bool keep = false;
1296 for (p = *head; p != NULL; p = p->next)
1297 if (p->count)
1298 {
1299 h->non_got_ref = 1;
1300 /* Need dynamic relocations for non-GOT reference. */
1301 keep = true;
1302 if (p->pc_count)
1303 {
1304 /* Must use PLT for PC-relative reference. */
1305 use_plt = true;
1306 need_dynreloc = bfd_link_pic (info);
1307 break;
1308 }
1309 }
1310 if (keep)
1311 goto keep;
1312 }
1313
1314 /* Support garbage collection against STT_GNU_IFUNC symbols. */
1315 if (h->plt.refcount <= 0 && h->got.refcount <= 0)
1316 {
1317 h->got = htab->init_got_offset;
1318 h->plt = htab->init_plt_offset;
1319 *head = NULL;
1320 return true;
1321 }
1322
1323 /* Return and discard space for dynamic relocations against it if
1324 it is never referenced. */
1325 if (!h->ref_regular)
1326 {
1327 if (h->plt.refcount > 0
1328 || h->got.refcount > 0)
1329 abort ();
1330 h->got = htab->init_got_offset;
1331 h->plt = htab->init_plt_offset;
1332 *head = NULL;
1333 return true;
1334 }
1335
1336 keep:
1337 bed = get_elf_backend_data (info->output_bfd);
1338 if (bed->rela_plts_and_copies_p)
1339 sizeof_reloc = bed->s->sizeof_rela;
1340 else
1341 sizeof_reloc = bed->s->sizeof_rel;
1342
1343 /* When building a static executable, use iplt, igot.plt and
1344 rela.iplt sections for STT_GNU_IFUNC symbols. */
1345 if (htab->splt != NULL)
1346 {
1347 plt = htab->splt;
1348 gotplt = htab->sgotplt;
1349 /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */
1350 relplt = htab->srelgot;
1351
1352 /* If this is the first plt entry and PLT is used, make room for
1353 the special first entry. */
1354 if (plt->size == 0 && use_plt)
1355 plt->size += plt_header_size;
1356 }
1357 else
1358 {
1359 plt = htab->iplt;
1360 gotplt = htab->igotplt;
1361 relplt = htab->irelplt;
1362 }
1363
1364 if (use_plt)
1365 {
1366 /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
1367 the original value for R_*_IRELATIVE. */
1368 h->plt.offset = plt->size;
1369
1370 /* Make room for this entry in the plt/iplt section. */
1371 plt->size += plt_entry_size;
1372
1373 /* We also need to make an entry in the got.plt/got.iplt section,
1374 which will be placed in the got section by the linker script. */
1375 gotplt->size += got_entry_size;
1376 }
1377
1378 /* We also need to make an entry in the rela.plt/.rela.iplt
1379 section for GOTPLT relocation if PLT is used. */
1380 if (use_plt)
1381 {
1382 relplt->size += sizeof_reloc;
1383 relplt->reloc_count++;
1384 }
1385
1386 /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
1387 there is a non-GOT reference in a PIC object or PLT isn't used. */
1388 if (!need_dynreloc || !h->non_got_ref)
1389 *head = NULL;
1390
1391 /* Finally, allocate space. */
1392 p = *head;
1393 if (p != NULL)
1394 {
1395 bfd_size_type count = 0;
1396 do
1397 {
1398 count += p->count;
1399 p = p->next;
1400 }
1401 while (p != NULL);
1402
1403 htab->ifunc_resolvers = count != 0;
1404
1405 /* Dynamic relocations are stored in
1406 1. rela.srelgot section in PIC object.
1407 2. rela.srelgot section in dynamic executable.
1408 3. rela.irelplt section in static executable. */
1409 if (htab->splt != NULL)
1410 htab->srelgot->size += count * sizeof_reloc;
1411 else
1412 {
1413 relplt->size += count * sizeof_reloc;
1414 relplt->reloc_count += count;
1415 }
1416 }
1417
1418 /* For STT_GNU_IFUNC symbol, got.plt has the real function address
1419 and got has the PLT entry adddress. We will load the GOT entry
1420 with the PLT entry in finish_dynamic_symbol if it is used. For
1421 branch, it uses got.plt. For symbol value, if PLT is used,
1422 1. Use got.plt in a PIC object if it is forced local or not
1423 dynamic.
1424 2. Use got.plt in a non-PIC object if pointer equality isn't
1425 needed.
1426 3. Use got.plt in PIE.
1427 4. Use got.plt if got isn't used.
1428 5. Otherwise use got so that it can be shared among different
1429 objects at run-time.
1430 If PLT isn't used, always use got for symbol value.
1431 We only need to relocate got entry in PIC object or in dynamic
1432 executable without PLT. */
1433 if (use_plt
1434 && (h->got.refcount <= 0
1435 || (bfd_link_pic (info)
1436 && (h->dynindx == -1
1437 || h->forced_local))
1438 || (
1439 !h->pointer_equality_needed)
1440 || htab->sgot == NULL))
1441 {
1442 /* Use got.plt. */
1443 h->got.offset = (bfd_vma) -1;
1444 }
1445 else
1446 {
1447 if (!use_plt)
1448 {
1449 /* PLT isn't used. */
1450 h->plt.offset = (bfd_vma) -1;
1451 }
1452 if (h->got.refcount <= 0)
1453 {
1454 /* GOT isn't need when there are only relocations for static
1455 pointers. */
1456 h->got.offset = (bfd_vma) -1;
1457 }
1458 else
1459 {
1460 h->got.offset = htab->sgot->size;
1461 htab->sgot->size += got_entry_size;
1462 /* Need to relocate the GOT entry in a PIC object or PLT isn't
1463 used. Otherwise, the GOT entry will be filled with the PLT
1464 entry and dynamic GOT relocation isn't needed. */
1465 if (need_dynreloc)
1466 {
1467 /* For non-static executable, dynamic GOT relocation is in
1468 rela.got section, but for static executable, it is
1469 in rela.iplt section. */
1470 if (htab->splt != NULL)
1471 htab->srelgot->size += sizeof_reloc;
1472 else
1473 {
1474 relplt->size += sizeof_reloc;
1475 relplt->reloc_count++;
1476 }
1477 }
1478 }
1479 }
1480
1481 return true;
1482}
1483
d218dba3 1484/* Allocate space in .plt, .got and associated reloc sections for
1485 ifunc dynamic relocs. */
1486
1487static bool
6d13722a 1488elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
d218dba3 1489{
1490 struct bfd_link_info *info;
1491 /* An example of a bfd_link_hash_indirect symbol is versioned
1492 symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
1493 -> __gxx_personality_v0(bfd_link_hash_defined)
1494
1495 There is no need to process bfd_link_hash_indirect symbols here
1496 because we will also be presented with the concrete instance of
1497 the symbol and loongarch_elf_copy_indirect_symbol () will have been
1498 called to copy all relevant data from the generic to the concrete
1499 symbol instance. */
1500 if (h->root.type == bfd_link_hash_indirect)
1501 return true;
1502
1503 if (h->root.type == bfd_link_hash_warning)
1504 h = (struct elf_link_hash_entry *) h->root.u.i.link;
1505
1506 info = (struct bfd_link_info *) inf;
1507
1508 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
1509 here if it is defined and referenced in a non-shared object. */
6d13722a 1510 if (h->type == STT_GNU_IFUNC && h->def_regular)
bc2a35c0 1511 {
1512 if (SYMBOL_REFERENCES_LOCAL (info, h))
1513 return local_allocate_ifunc_dyn_relocs (info, h,
1514 &h->dyn_relocs,
1515 PLT_ENTRY_SIZE,
1516 PLT_HEADER_SIZE,
1517 GOT_ENTRY_SIZE,
1518 false);
1519 else
1520 return _bfd_elf_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 }
6d13722a 1527
d218dba3 1528 return true;
1529}
1530
1531/* Allocate space in .plt, .got and associated reloc sections for
1532 ifunc dynamic relocs. */
1533
e214f8db 1534static bool
6d13722a 1535elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
e214f8db 1536{
1537 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
1538
d218dba3 1539 if (h->type != STT_GNU_IFUNC
1540 || !h->def_regular
1541 || !h->ref_regular
1542 || !h->forced_local
e214f8db 1543 || h->root.type != bfd_link_hash_defined)
1544 abort ();
1545
6d13722a 1546 return elfNN_allocate_ifunc_dynrelocs (h, inf);
e214f8db 1547}
1548
1549/* Set DF_TEXTREL if we find any dynamic relocs that apply to
1550 read-only sections. */
1551
1552static bool
1553maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
1554{
1555 asection *sec;
1556
1557 if (h->root.type == bfd_link_hash_indirect)
1558 return true;
1559
1560 sec = readonly_dynrelocs (h);
1561 if (sec != NULL)
1562 {
1563 struct bfd_link_info *info = (struct bfd_link_info *) info_p;
1564
1565 info->flags |= DF_TEXTREL;
1566 info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' in "
1567 "read-only section `%pA'\n"),
1568 sec->owner, h->root.root.string, sec);
1569
1570 /* Not an error, just cut short the traversal. */
1571 return false;
1572 }
1573 return true;
1574}
1575
1576static bool
1577loongarch_elf_size_dynamic_sections (bfd *output_bfd,
1578 struct bfd_link_info *info)
1579{
1580 struct loongarch_elf_link_hash_table *htab;
1581 bfd *dynobj;
1582 asection *s;
1583 bfd *ibfd;
1584
1585 htab = loongarch_elf_hash_table (info);
1586 BFD_ASSERT (htab != NULL);
1587 dynobj = htab->elf.dynobj;
1588 BFD_ASSERT (dynobj != NULL);
1589
1590 if (htab->elf.dynamic_sections_created)
1591 {
1592 /* Set the contents of the .interp section to the interpreter. */
1593 if (bfd_link_executable (info) && !info->nointerp)
1594 {
1595 const char *interpreter;
e214f8db 1596 s = bfd_get_linker_section (dynobj, ".interp");
1597 BFD_ASSERT (s != NULL);
c4a7e6b5 1598
1599 if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS32)
e214f8db 1600 interpreter = "/lib32/ld.so.1";
c4a7e6b5 1601 else if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS64)
e214f8db 1602 interpreter = "/lib64/ld.so.1";
1603 else
1604 interpreter = "/lib/ld.so.1";
c4a7e6b5 1605
e214f8db 1606 s->contents = (unsigned char *) interpreter;
1607 s->size = strlen (interpreter) + 1;
1608 }
1609 }
1610
1611 /* Set up .got offsets for local syms, and space for local dynamic
1612 relocs. */
1613 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
1614 {
1615 bfd_signed_vma *local_got;
1616 bfd_signed_vma *end_local_got;
1617 char *local_tls_type;
1618 bfd_size_type locsymcount;
1619 Elf_Internal_Shdr *symtab_hdr;
1620 asection *srel;
1621
1622 if (!is_loongarch_elf (ibfd))
1623 continue;
1624
1625 for (s = ibfd->sections; s != NULL; s = s->next)
1626 {
1627 struct elf_dyn_relocs *p;
1628
1629 for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
1630 {
1631 p->count -= p->pc_count;
1632 if (!bfd_is_abs_section (p->sec)
1633 && bfd_is_abs_section (p->sec->output_section))
1634 {
1635 /* Input section has been discarded, either because
1636 it is a copy of a linkonce section or due to
1637 linker script /DISCARD/, so we'll be discarding
1638 the relocs too. */
1639 }
1640 else if (0 < p->count)
1641 {
1642 srel = elf_section_data (p->sec)->sreloc;
1643 srel->size += p->count * sizeof (ElfNN_External_Rela);
1644 if ((p->sec->output_section->flags & SEC_READONLY) != 0)
1645 info->flags |= DF_TEXTREL;
1646 }
1647 }
1648 }
1649
1650 local_got = elf_local_got_refcounts (ibfd);
1651 if (!local_got)
1652 continue;
1653
1654 symtab_hdr = &elf_symtab_hdr (ibfd);
1655 locsymcount = symtab_hdr->sh_info;
1656 end_local_got = local_got + locsymcount;
1657 local_tls_type = _bfd_loongarch_elf_local_got_tls_type (ibfd);
1658 s = htab->elf.sgot;
1659 srel = htab->elf.srelgot;
1660 for (; local_got < end_local_got; ++local_got, ++local_tls_type)
1661 {
1662 if (0 < *local_got)
1663 {
1664 *local_got = s->size;
e214f8db 1665
6d13722a 1666 /* TLS gd use two got. */
e214f8db 1667 if (*local_tls_type & GOT_TLS_GD)
6d13722a 1668 s->size += GOT_ENTRY_SIZE * 2;
1669 else
1670 /* Normal got, tls ie/ld use one got. */
e214f8db 1671 s->size += GOT_ENTRY_SIZE;
1672
6d13722a 1673 if (bfd_link_executable (info)
1674 && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
1675 ;/* Do nothing. */
1676 else
1677 {
1678 srel->size += sizeof (ElfNN_External_Rela);
1679 }
e214f8db 1680 }
1681 else
1682 *local_got = MINUS_ONE;
1683 }
1684 }
1685
1686 /* Allocate global sym .plt and .got entries, and space for global
1687 sym dynamic relocs. */
1688 elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
d218dba3 1689
1690 /* Allocate global ifunc sym .plt and .got entries, and space for global
1691 ifunc sym dynamic relocs. */
6d13722a 1692 elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info);
d218dba3 1693
e214f8db 1694 /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1695 htab_traverse (htab->loc_hash_table,
6d13722a 1696 (void *) elfNN_allocate_local_ifunc_dynrelocs, info);
e214f8db 1697
1698 /* Don't allocate .got.plt section if there are no PLT. */
1699 if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE
1700 && (htab->elf.splt == NULL || htab->elf.splt->size == 0))
1701 htab->elf.sgotplt->size = 0;
1702
1703 /* The check_relocs and adjust_dynamic_symbol entry points have
1704 determined the sizes of the various dynamic sections. Allocate
1705 memory for them. */
1706 for (s = dynobj->sections; s != NULL; s = s->next)
1707 {
1708 if ((s->flags & SEC_LINKER_CREATED) == 0)
1709 continue;
1710
1711 if (s == htab->elf.splt || s == htab->elf.iplt || s == htab->elf.sgot
1712 || s == htab->elf.sgotplt || s == htab->elf.igotplt
1713 || s == htab->elf.sdynbss || s == htab->elf.sdynrelro)
1714 {
1715 /* Strip this section if we don't need it; see the
1716 comment below. */
1717 }
1718 else if (strncmp (s->name, ".rela", 5) == 0)
1719 {
1720 if (s->size != 0)
1721 {
1722 /* We use the reloc_count field as a counter if we need
1723 to copy relocs into the output file. */
1724 s->reloc_count = 0;
1725 }
1726 }
1727 else
1728 {
1729 /* It's not one of our sections. */
1730 continue;
1731 }
1732
1733 if (s->size == 0)
1734 {
1735 /* If we don't need this section, strip it from the
1736 output file. This is mostly to handle .rela.bss and
1737 .rela.plt. We must create both sections in
1738 create_dynamic_sections, because they must be created
1739 before the linker maps input sections to output
1740 sections. The linker does that before
1741 adjust_dynamic_symbol is called, and it is that
1742 function which decides whether anything needs to go
1743 into these sections. */
1744 s->flags |= SEC_EXCLUDE;
1745 continue;
1746 }
1747
1748 if ((s->flags & SEC_HAS_CONTENTS) == 0)
1749 continue;
1750
1751 /* Allocate memory for the section contents. Zero the memory
1752 for the benefit of .rela.plt, which has 4 unused entries
1753 at the beginning, and we don't want garbage. */
1754 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
1755 if (s->contents == NULL)
1756 return false;
1757 }
1758
1759 if (elf_hash_table (info)->dynamic_sections_created)
1760 {
1761 /* Add some entries to the .dynamic section. We fill in the
1762 values later, in loongarch_elf_finish_dynamic_sections, but we
1763 must add the entries now so that we get the correct size for
1764 the .dynamic section. The DT_DEBUG entry is filled in by the
1765 dynamic linker and used by the debugger. */
1766#define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1767
1768 if (bfd_link_executable (info))
1769 {
1770 if (!add_dynamic_entry (DT_DEBUG, 0))
1771 return false;
1772 }
1773
1774 if (htab->elf.srelplt->size != 0)
1775 {
1776 if (!add_dynamic_entry (DT_PLTGOT, 0)
1777 || !add_dynamic_entry (DT_PLTRELSZ, 0)
1778 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
1779 || !add_dynamic_entry (DT_JMPREL, 0))
1780 return false;
1781 }
1782
1783 if (!add_dynamic_entry (DT_RELA, 0)
1784 || !add_dynamic_entry (DT_RELASZ, 0)
1785 || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
1786 return false;
1787
1788 /* If any dynamic relocs apply to a read-only section,
1789 then we need a DT_TEXTREL entry. */
1790 if ((info->flags & DF_TEXTREL) == 0)
1791 elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
1792
1793 if (info->flags & DF_TEXTREL)
1794 {
1795 if (!add_dynamic_entry (DT_TEXTREL, 0))
1796 return false;
1797 /* Clear the DF_TEXTREL flag. It will be set again if we
1798 write out an actual text relocation; we may not, because
1799 at this point we do not know whether e.g. any .eh_frame
1800 absolute relocations have been converted to PC-relative. */
1801 info->flags &= ~DF_TEXTREL;
1802 }
1803 }
1804#undef add_dynamic_entry
1805
1806 return true;
1807}
1808
1809#define LARCH_LD_STACK_DEPTH 16
1810static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
1811static size_t larch_stack_top = 0;
1812
1813static bfd_reloc_status_type
1814loongarch_push (int64_t val)
1815{
1816 if (LARCH_LD_STACK_DEPTH <= larch_stack_top)
1817 return bfd_reloc_outofrange;
1818 larch_opc_stack[larch_stack_top++] = val;
1819 return bfd_reloc_ok;
1820}
1821
1822static bfd_reloc_status_type
1823loongarch_pop (int64_t *val)
1824{
1825 if (larch_stack_top == 0)
1826 return bfd_reloc_outofrange;
1827 BFD_ASSERT (val);
1828 *val = larch_opc_stack[--larch_stack_top];
1829 return bfd_reloc_ok;
1830}
1831
1832static bfd_reloc_status_type
1833loongarch_top (int64_t *val)
1834{
1835 if (larch_stack_top == 0)
1836 return bfd_reloc_outofrange;
1837 BFD_ASSERT (val);
1838 *val = larch_opc_stack[larch_stack_top - 1];
1839 return bfd_reloc_ok;
1840}
1841
1842static void
1843loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
1844{
6d13722a 1845 BFD_ASSERT (s && s->contents);
e214f8db 1846 const struct elf_backend_data *bed;
1847 bfd_byte *loc;
1848
1849 bed = get_elf_backend_data (abfd);
6d13722a 1850 if (!(s->size > s->reloc_count * bed->s->sizeof_rela))
1851 BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela);
e214f8db 1852 loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
1853 bed->s->swap_reloca_out (abfd, rel, loc);
1854}
1855
1856/* Check rel->r_offset in range of contents. */
1857static bfd_reloc_status_type
1858loongarch_check_offset (const Elf_Internal_Rela *rel,
1859 const asection *input_section)
1860{
1861 if (0 == strcmp(input_section->name, ".text")
1862 && rel->r_offset > input_section->size)
1863 return bfd_reloc_overflow;
1864
1865 return bfd_reloc_ok;
1866}
1867
e214f8db 1868#define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1869 ({ \
1870 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1871 if (ret == bfd_reloc_ok) \
1872 { \
1873 ret = loongarch_pop (&op1); \
1874 if (ret == bfd_reloc_ok) \
1875 ret = loongarch_push (op3); \
1876 } \
1877 ret; \
1878 })
1879
e214f8db 1880static bfd_reloc_status_type
1881loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
1882 const asection *input_section ATTRIBUTE_UNUSED,
1883 reloc_howto_type *howto, bfd *input_bfd,
748594bc 1884 bfd_byte *contents, bfd_vma reloc_val)
e214f8db 1885{
e214f8db 1886 int bits = bfd_get_reloc_size (howto) * 8;
1887 uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
1888
748594bc 1889 if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
1890 return bfd_reloc_overflow;
1891
1892 insn = (insn & (uint32_t)howto->src_mask)
1893 | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val);
1894
e214f8db 1895 bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
1896
1897 return bfd_reloc_ok;
1898}
1899
e214f8db 1900static bfd_reloc_status_type
1901perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
1902 reloc_howto_type *howto, bfd_vma value,
1903 bfd *input_bfd, bfd_byte *contents)
1904{
e214f8db 1905 int64_t opr1, opr2, opr3;
1906 bfd_reloc_status_type r = bfd_reloc_ok;
1907 int bits = bfd_get_reloc_size (howto) * 8;
1908
e214f8db 1909 switch (ELFNN_R_TYPE (rel->r_info))
1910 {
1911 case R_LARCH_SOP_PUSH_PCREL:
1912 case R_LARCH_SOP_PUSH_ABSOLUTE:
1913 case R_LARCH_SOP_PUSH_GPREL:
1914 case R_LARCH_SOP_PUSH_TLS_TPREL:
1915 case R_LARCH_SOP_PUSH_TLS_GOT:
1916 case R_LARCH_SOP_PUSH_TLS_GD:
1917 case R_LARCH_SOP_PUSH_PLT_PCREL:
1918 r = loongarch_push (value);
1919 break;
1920
1921 case R_LARCH_SOP_PUSH_DUP:
1922 r = loongarch_pop (&opr1);
1923 if (r == bfd_reloc_ok)
1924 {
1925 r = loongarch_push (opr1);
1926 if (r == bfd_reloc_ok)
1927 r = loongarch_push (opr1);
1928 }
1929 break;
1930
1931 case R_LARCH_SOP_ASSERT:
1932 r = loongarch_pop (&opr1);
1933 if (r != bfd_reloc_ok || !opr1)
1934 r = bfd_reloc_notsupported;
1935 break;
1936
1937 case R_LARCH_SOP_NOT:
1938 r = loongarch_pop (&opr1);
1939 if (r == bfd_reloc_ok)
1940 r = loongarch_push (!opr1);
1941 break;
1942
1943 case R_LARCH_SOP_SUB:
1944 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
1945 break;
1946
1947 case R_LARCH_SOP_SL:
1948 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
1949 break;
1950
1951 case R_LARCH_SOP_SR:
1952 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
1953 break;
1954
1955 case R_LARCH_SOP_AND:
1956 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
1957 break;
1958
1959 case R_LARCH_SOP_ADD:
1960 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
1961 break;
1962
1963 case R_LARCH_SOP_IF_ELSE:
1964 r = loongarch_pop (&opr3);
1965 if (r == bfd_reloc_ok)
1966 {
1967 r = loongarch_pop (&opr2);
1968 if (r == bfd_reloc_ok)
1969 {
1970 r = loongarch_pop (&opr1);
1971 if (r == bfd_reloc_ok)
1972 r = loongarch_push (opr1 ? opr2 : opr3);
1973 }
1974 }
1975 break;
1976
1977 case R_LARCH_SOP_POP_32_S_10_5:
1978 case R_LARCH_SOP_POP_32_S_10_12:
1979 case R_LARCH_SOP_POP_32_S_10_16:
1980 case R_LARCH_SOP_POP_32_S_10_16_S2:
6d13722a 1981 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1982 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
e214f8db 1983 case R_LARCH_SOP_POP_32_S_5_20:
e214f8db 1984 case R_LARCH_SOP_POP_32_U_10_12:
748594bc 1985 case R_LARCH_SOP_POP_32_U:
e214f8db 1986 r = loongarch_pop (&opr1);
1987 if (r != bfd_reloc_ok)
1988 break;
1989 r = loongarch_check_offset (rel, input_section);
1990 if (r != bfd_reloc_ok)
1991 break;
1992
1993 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
1994 howto, input_bfd,
748594bc 1995 contents, (bfd_vma)opr1);
e214f8db 1996 break;
1997
e214f8db 1998 case R_LARCH_TLS_DTPREL32:
1999 case R_LARCH_32:
2000 case R_LARCH_TLS_DTPREL64:
2001 case R_LARCH_64:
2002 r = loongarch_check_offset (rel, input_section);
2003 if (r != bfd_reloc_ok)
2004 break;
2005
2006 bfd_put (bits, input_bfd, value, contents + rel->r_offset);
2007 break;
2008
2009 case R_LARCH_ADD8:
2010 case R_LARCH_ADD16:
2011 case R_LARCH_ADD24:
2012 case R_LARCH_ADD32:
2013 case R_LARCH_ADD64:
2014 r = loongarch_check_offset (rel, input_section);
2015 if (r != bfd_reloc_ok)
2016 break;
2017
2018 opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
2019 bfd_put (bits, input_bfd, opr1 + value, contents + rel->r_offset);
2020 break;
2021
2022 case R_LARCH_SUB8:
2023 case R_LARCH_SUB16:
2024 case R_LARCH_SUB24:
2025 case R_LARCH_SUB32:
2026 case R_LARCH_SUB64:
2027 r = loongarch_check_offset (rel, input_section);
2028 if (r != bfd_reloc_ok)
2029 break;
2030
2031 opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
2032 bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
2033 break;
2034
98011207 2035 /* For eh_frame and debug info. */
2036 case R_LARCH_32_PCREL:
2037 value -= sec_addr (input_section) + rel->r_offset;
2038 value += rel->r_addend;
2039 bfd_vma word = bfd_get (howto->bitsize, input_bfd,
2040 contents + rel->r_offset);
2041 word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
2042 bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
2043 r = bfd_reloc_ok;
2044 break;
2045
6d13722a 2046 /* New reloc type.
2047 R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */
2048 case R_LARCH_B16:
2049 case R_LARCH_B21:
2050 case R_LARCH_B26:
2051 case R_LARCH_ABS_HI20:
2052 case R_LARCH_ABS_LO12:
2053 case R_LARCH_ABS64_LO20:
2054 case R_LARCH_ABS64_HI12:
2055 case R_LARCH_PCALA_HI20:
2056 case R_LARCH_PCALA_LO12:
2057 case R_LARCH_PCALA64_LO20:
2058 case R_LARCH_PCALA64_HI12:
2059 case R_LARCH_GOT_PC_HI20:
2060 case R_LARCH_GOT_PC_LO12:
2061 case R_LARCH_GOT64_PC_LO20:
2062 case R_LARCH_GOT64_PC_HI12:
2063 case R_LARCH_GOT_HI20:
2064 case R_LARCH_GOT_LO12:
2065 case R_LARCH_GOT64_LO20:
2066 case R_LARCH_GOT64_HI12:
2067 case R_LARCH_TLS_LE_HI20:
2068 case R_LARCH_TLS_LE_LO12:
2069 case R_LARCH_TLS_LE64_LO20:
2070 case R_LARCH_TLS_LE64_HI12:
2071 case R_LARCH_TLS_IE_PC_HI20:
2072 case R_LARCH_TLS_IE_PC_LO12:
2073 case R_LARCH_TLS_IE64_PC_LO20:
2074 case R_LARCH_TLS_IE64_PC_HI12:
2075 case R_LARCH_TLS_IE_HI20:
2076 case R_LARCH_TLS_IE_LO12:
2077 case R_LARCH_TLS_IE64_LO20:
2078 case R_LARCH_TLS_IE64_HI12:
2079 case R_LARCH_TLS_LD_PC_HI20:
2080 case R_LARCH_TLS_LD_HI20:
2081 case R_LARCH_TLS_GD_PC_HI20:
2082 case R_LARCH_TLS_GD_HI20:
2083 r = loongarch_check_offset (rel, input_section);
2084 if (r != bfd_reloc_ok)
2085 break;
2086
2087 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
2088 howto, input_bfd,
2089 contents, value);
2090 break;
2091
2092 case R_LARCH_RELAX:
2093 break;
2094
e214f8db 2095 default:
2096 r = bfd_reloc_notsupported;
2097 }
2098 return r;
2099}
2100
2101#define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
2102static struct
2103{
2104 bfd *bfd;
2105 asection *section;
2106 bfd_vma r_offset;
2107 int r_type;
2108 bfd_vma relocation;
2109 Elf_Internal_Sym *sym;
2110 struct elf_link_hash_entry *h;
2111 bfd_vma addend;
2112 int64_t top_then;
2113} larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
2114static size_t larch_reloc_queue_head = 0;
2115static size_t larch_reloc_queue_tail = 0;
2116
2117static const char *
2118loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
2119 Elf_Internal_Sym *sym)
2120{
2121 const char *ret = NULL;
2122 if (sym)
2123 ret = bfd_elf_string_from_elf_section (input_bfd,
2124 elf_symtab_hdr (input_bfd).sh_link,
2125 sym->st_name);
2126 else if (h)
2127 ret = h->root.root.string;
2128
2129 if (ret == NULL || *ret == '\0')
2130 ret = "<nameless>";
2131 return ret;
2132}
2133
2134static void
2135loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
2136 bfd_vma r_offset, Elf_Internal_Sym *sym,
2137 struct elf_link_hash_entry *h, bfd_vma addend)
2138{
2139 if ((larch_reloc_queue_head == 0
2140 && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
2141 || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
2142 larch_reloc_queue_head =
2143 (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2144 larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
2145 larch_reloc_queue[larch_reloc_queue_tail].section = section;
2146 larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
2147 larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
2148 larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
2149 larch_reloc_queue[larch_reloc_queue_tail].h = h;
2150 larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
2151 loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
2152 larch_reloc_queue_tail =
2153 (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2154}
2155
2156static void
2157loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
2158{
2159 size_t i = larch_reloc_queue_head;
2160 bfd *a_bfd = NULL;
2161 asection *section = NULL;
2162 bfd_vma r_offset = 0;
2163 int inited = 0;
2164 p ("Dump relocate record:\n");
2165 p ("stack top\t\trelocation name\t\tsymbol");
2166 while (i != larch_reloc_queue_tail)
2167 {
2168 if (a_bfd != larch_reloc_queue[i].bfd
2169 || section != larch_reloc_queue[i].section
2170 || r_offset != larch_reloc_queue[i].r_offset)
2171 {
2172 a_bfd = larch_reloc_queue[i].bfd;
2173 section = larch_reloc_queue[i].section;
2174 r_offset = larch_reloc_queue[i].r_offset;
2175 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
2176 larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
2177 }
2178
2179 if (!inited)
2180 inited = 1, p ("...\n");
2181
2182 reloc_howto_type *howto =
2183 loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
2184 larch_reloc_queue[i].r_type);
2185 p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
2186 howto ? howto->name : "<unknown reloc>",
2187 loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
2188 larch_reloc_queue[i].sym));
2189
2190 long addend = larch_reloc_queue[i].addend;
2191 if (addend < 0)
2192 p (" - %ld", -addend);
2193 else if (0 < addend)
2194 p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
2195
2196 p ("\n");
2197 i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
2198 }
2199 p ("\n"
2200 "-- Record dump end --\n\n");
2201}
2202
e214f8db 2203static bool
2204loongarch_reloc_is_fatal (struct bfd_link_info *info,
2205 bfd *input_bfd,
2206 asection *input_section,
2207 Elf_Internal_Rela *rel,
2208 reloc_howto_type *howto,
2209 bfd_reloc_status_type rtype,
2210 bool is_undefweak,
2211 const char *name,
2212 const char *msg)
2213{
2214 bool fatal = true;
2215 switch (rtype)
2216 {
2217 /* 'dangerous' means we do it but can't promise it's ok
2218 'unsupport' means out of ability of relocation type
2219 'undefined' means we can't deal with the undefined symbol. */
2220 case bfd_reloc_undefined:
2221 info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
2222 rel->r_offset, true);
2223 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2224 input_bfd, input_section, rel->r_offset,
2225 howto->name,
2226 is_undefweak ? "[undefweak] " : "", name, msg);
2227 break;
2228 case bfd_reloc_dangerous:
2229 info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
2230 input_bfd, input_section, rel->r_offset,
2231 howto->name,
2232 is_undefweak ? "[undefweak] " : "", name, msg);
2233 fatal = false;
2234 break;
2235 case bfd_reloc_notsupported:
2236 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
2237 input_bfd, input_section, rel->r_offset,
2238 howto->name,
2239 is_undefweak ? "[undefweak] " : "", name, msg);
2240 break;
2241 default:
2242 break;
2243 }
2244 return fatal;
2245}
2246
6d13722a 2247#define RELOCATE_CALC_PC32_HI20(relocation, pc) \
2248 ({ \
2249 bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2250 pc = pc & (~(bfd_vma)0xfff); \
2251 if (lo > 0x7ff) \
2252 { \
2253 relocation += 0x1000; \
2254 } \
2255 relocation &= ~(bfd_vma)0xfff; \
2256 relocation -= pc; \
2257 })
2258
2259#define RELOCATE_CALC_PC64_HI32(relocation, pc) \
2260 ({ \
2261 bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
2262 if (lo > 0x7ff) \
2263 { \
2264 relocation -= 0x100000000; \
2265 } \
2266 relocation -= (pc & ~(bfd_vma)0xffffffff); \
2267 })
e214f8db 2268
2269static int
2270loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
2271 bfd *input_bfd, asection *input_section,
2272 bfd_byte *contents, Elf_Internal_Rela *relocs,
2273 Elf_Internal_Sym *local_syms,
2274 asection **local_sections)
2275{
2276 Elf_Internal_Rela *rel;
2277 Elf_Internal_Rela *relend;
2278 bool fatal = false;
2279 asection *sreloc = elf_section_data (input_section)->sreloc;
2280 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2281 Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
2282 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
2283 bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
2284 bool is_pic = bfd_link_pic (info);
2285 bool is_dyn = elf_hash_table (info)->dynamic_sections_created;
2286 asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
2287 asection *got = htab->elf.sgot;
2288
2289 relend = relocs + input_section->reloc_count;
2290 for (rel = relocs; rel < relend; rel++)
2291 {
2292 int r_type = ELFNN_R_TYPE (rel->r_info);
2293 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
2294 bfd_vma pc = sec_addr (input_section) + rel->r_offset;
2295 reloc_howto_type *howto = NULL;
2296 asection *sec = NULL;
2297 Elf_Internal_Sym *sym = NULL;
2298 struct elf_link_hash_entry *h = NULL;
2299 const char *name;
2300 bfd_reloc_status_type r = bfd_reloc_ok;
2301 bool is_ie, is_undefweak, unresolved_reloc, defined_local;
2302 bool resolved_local, resolved_dynly, resolved_to_const;
2303 char tls_type;
6d13722a 2304 bfd_vma relocation, off, ie_off;
e214f8db 2305 int i, j;
2306
2307 howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
2308 if (howto == NULL || r_type == R_LARCH_GNU_VTINHERIT
2309 || r_type == R_LARCH_GNU_VTENTRY)
2310 continue;
2311
2312 /* This is a final link. */
2313 if (r_symndx < symtab_hdr->sh_info)
2314 {
2315 is_undefweak = false;
2316 unresolved_reloc = false;
2317 sym = local_syms + r_symndx;
2318 sec = local_sections[r_symndx];
2319 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
2320
2321 /* Relocate against local STT_GNU_IFUNC symbol. */
2322 if (!bfd_link_relocatable (info)
2323 && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
2324 {
2325 h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
2326 false);
2327 if (h == NULL)
2328 abort ();
2329
2330 /* Set STT_GNU_IFUNC symbol value. */
2331 h->root.u.def.value = sym->st_value;
2332 h->root.u.def.section = sec;
2333 }
2334 defined_local = true;
2335 resolved_local = true;
2336 resolved_dynly = false;
2337 resolved_to_const = false;
6d13722a 2338
2339 /* Calc in funtion elf_link_input_bfd,
2340 * if #define elf_backend_rela_normal to 1. */
e214f8db 2341 if (bfd_link_relocatable (info)
2342 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
6d13722a 2343 continue;
e214f8db 2344 }
2345 else
2346 {
2347 bool warned, ignored;
2348
2349 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
2350 r_symndx, symtab_hdr, sym_hashes,
2351 h, sec, relocation,
2352 unresolved_reloc, warned, ignored);
2353 /* Here means symbol isn't local symbol only and 'h != NULL'. */
2354
2355 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
2356 symbol. And 'dynamic_undefined_weak' specify what to do when
2357 meeting undefweak. */
2358
2359 if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
2360 {
2361 defined_local = false;
2362 resolved_local = false;
2363 resolved_to_const = (!is_dyn || h->dynindx == -1
2364 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
2365 resolved_dynly = !resolved_local && !resolved_to_const;
2366 }
2367 else if (warned)
2368 {
2369 /* Symbol undefined offen means failed already. I don't know why
2370 'warned' here but I guess it want to continue relocating as if
2371 no error occures to find other errors as more as possible. */
2372
2373 /* To avoid generating warning messages about truncated
2374 relocations, set the relocation's address to be the same as
2375 the start of this section. */
2376 relocation = (input_section->output_section
2377 ? input_section->output_section->vma
2378 : 0);
2379
2380 defined_local = relocation != 0;
2381 resolved_local = defined_local;
2382 resolved_to_const = !resolved_local;
2383 resolved_dynly = false;
2384 }
2385 else
2386 {
2387 defined_local = !unresolved_reloc && !ignored;
2388 resolved_local =
2389 defined_local && SYMBOL_REFERENCES_LOCAL (info, h);
2390 resolved_dynly = !resolved_local;
2391 resolved_to_const = !resolved_local && !resolved_dynly;
2392 }
2393 }
2394
2395 name = loongarch_sym_name (input_bfd, h, sym);
2396
2397 if (sec != NULL && discarded_section (sec))
2398 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
2399 1, relend, howto, 0, contents);
2400
2401 if (bfd_link_relocatable (info))
2402 continue;
2403
2404 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2405 from removed linkonce sections, or sections discarded by a linker
2406 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2407 if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
2408 {
2409 defined_local = false;
2410 resolved_local = false;
2411 resolved_dynly = false;
2412 resolved_to_const = true;
2413 }
2414
6d13722a 2415 /* The ifunc reference generate plt. */
d218dba3 2416 if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE)
e214f8db 2417 {
e214f8db 2418 defined_local = true;
2419 resolved_local = true;
2420 resolved_dynly = false;
2421 resolved_to_const = false;
2422 relocation = sec_addr (plt) + h->plt.offset;
2423 }
2424
2425 unresolved_reloc = resolved_dynly;
2426
2427 BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
2428
d218dba3 2429 /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));. */
e214f8db 2430
2431 BFD_ASSERT (!resolved_local || defined_local);
2432
2433 is_ie = false;
2434 switch (r_type)
2435 {
2436 case R_LARCH_MARK_PCREL:
2437 case R_LARCH_MARK_LA:
2438 case R_LARCH_NONE:
2439 r = bfd_reloc_continue;
2440 unresolved_reloc = false;
2441 break;
2442
2443 case R_LARCH_32:
2444 case R_LARCH_64:
2445 if (resolved_dynly || (is_pic && resolved_local))
2446 {
2447 Elf_Internal_Rela outrel;
2448
2449 /* When generating a shared object, these relocations are copied
2450 into the output file to be resolved at run time. */
2451
2452 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2453 input_section,
2454 rel->r_offset);
2455
2456 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2457 && (input_section->flags & SEC_ALLOC));
2458
2459 outrel.r_offset += sec_addr (input_section);
d218dba3 2460
bc2a35c0 2461 /* A pointer point to a ifunc symbol. */
2462 if (h && h->type == STT_GNU_IFUNC)
d218dba3 2463 {
bc2a35c0 2464 if (h->dynindx == -1)
2465 {
2466 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2467 outrel.r_addend = (h->root.u.def.value
2468 + h->root.u.def.section->output_section->vma
2469 + h->root.u.def.section->output_offset);
2470 }
2471 else
2472 {
2473 outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
2474 outrel.r_addend = 0;
2475 }
d218dba3 2476
bc2a35c0 2477 if (SYMBOL_REFERENCES_LOCAL (info, h))
2478 {
2479
2480 if (htab->elf.splt != NULL)
2481 sreloc = htab->elf.srelgot;
2482 else
2483 sreloc = htab->elf.irelplt;
2484 }
d218dba3 2485 else
bc2a35c0 2486 {
2487
2488 if (bfd_link_pic (info))
2489 sreloc = htab->elf.irelifunc;
2490 else if (htab->elf.splt != NULL)
2491 sreloc = htab->elf.srelgot;
2492 else
2493 sreloc = htab->elf.irelplt;
2494 }
d218dba3 2495 }
2496 else if (resolved_dynly)
e214f8db 2497 {
6d13722a 2498 if (h->dynindx == -1)
2499 {
2500 if (h->root.type == bfd_link_hash_undefined)
2501 (*info->callbacks->undefined_symbol)
2502 (info, name, input_bfd, input_section,
2503 rel->r_offset, true);
2504
2505 outrel.r_info = ELFNN_R_INFO (0, r_type);
2506 }
2507 else
2508 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2509
e214f8db 2510 outrel.r_addend = rel->r_addend;
2511 }
2512 else
2513 {
2514 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2515 outrel.r_addend = relocation + rel->r_addend;
2516 }
2517
6d13722a 2518 /* No alloc space of func allocate_dynrelocs. */
2519 if (unresolved_reloc
2520 && !(h && (h->is_weakalias || !h->dyn_relocs)))
e214f8db 2521 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2522 }
2523
2524 relocation += rel->r_addend;
2525 break;
2526
2527 case R_LARCH_ADD8:
2528 case R_LARCH_ADD16:
2529 case R_LARCH_ADD24:
2530 case R_LARCH_ADD32:
2531 case R_LARCH_ADD64:
2532 case R_LARCH_SUB8:
2533 case R_LARCH_SUB16:
2534 case R_LARCH_SUB24:
2535 case R_LARCH_SUB32:
2536 case R_LARCH_SUB64:
2537 if (resolved_dynly)
2538 fatal = (loongarch_reloc_is_fatal
2539 (info, input_bfd, input_section, rel, howto,
2540 bfd_reloc_undefined, is_undefweak, name,
2541 "Can't be resolved dynamically. "
2542 "If this procedure is hand-written assembly,\n"
2543 "there must be something like '.dword sym1 - sym2' "
2544 "to generate these relocs\n"
2545 "and we can't get known link-time address of "
2546 "these symbols."));
2547 else
2548 relocation += rel->r_addend;
2549 break;
2550
2551 case R_LARCH_TLS_DTPREL32:
2552 case R_LARCH_TLS_DTPREL64:
2553 if (resolved_dynly)
2554 {
2555 Elf_Internal_Rela outrel;
2556
2557 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2558 input_section,
2559 rel->r_offset);
2560 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2561 && (input_section->flags & SEC_ALLOC));
2562 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2563 outrel.r_offset += sec_addr (input_section);
2564 outrel.r_addend = rel->r_addend;
2565 if (unresolved_reloc)
2566 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2567 break;
2568 }
2569
2570 if (resolved_to_const)
2571 fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
2572 rel, howto,
2573 bfd_reloc_notsupported,
2574 is_undefweak, name,
2575 "Internal:");
d218dba3 2576 if (resolved_local)
2577 {
2578 if (!elf_hash_table (info)->tls_sec)
2579 {
2580 fatal = loongarch_reloc_is_fatal (info, input_bfd,
2581 input_section, rel, howto, bfd_reloc_notsupported,
2582 is_undefweak, name, "TLS section not be created");
2583 }
2584 else
2585 relocation -= elf_hash_table (info)->tls_sec->vma;
2586 }
2587 else
2588 {
2589 fatal = loongarch_reloc_is_fatal (info, input_bfd,
2590 input_section, rel, howto, bfd_reloc_undefined,
2591 is_undefweak, name,
2592 "TLS LE just can be resolved local only.");
2593 }
2594
e214f8db 2595 break;
2596
2597 case R_LARCH_SOP_PUSH_TLS_TPREL:
2598 if (resolved_local)
2599 {
2600 if (!elf_hash_table (info)->tls_sec)
2601 fatal = (loongarch_reloc_is_fatal
2602 (info, input_bfd, input_section, rel, howto,
2603 bfd_reloc_notsupported, is_undefweak, name,
2604 "TLS section not be created"));
2605 else
2606 relocation -= elf_hash_table (info)->tls_sec->vma;
2607 }
2608 else
2609 fatal = (loongarch_reloc_is_fatal
2610 (info, input_bfd, input_section, rel, howto,
2611 bfd_reloc_undefined, is_undefweak, name,
2612 "TLS LE just can be resolved local only."));
2613 break;
2614
2615 case R_LARCH_SOP_PUSH_ABSOLUTE:
2616 if (is_undefweak)
2617 {
2618 if (resolved_dynly)
2619 fatal = (loongarch_reloc_is_fatal
2620 (info, input_bfd, input_section, rel, howto,
2621 bfd_reloc_dangerous, is_undefweak, name,
2622 "Someone require us to resolve undefweak "
2623 "symbol dynamically. \n"
2624 "But this reloc can't be done. "
2625 "I think I can't throw error "
2626 "for this\n"
2627 "so I resolved it to 0. "
2628 "I suggest to re-compile with '-fpic'."));
2629
2630 relocation = 0;
2631 unresolved_reloc = false;
2632 break;
2633 }
2634
2635 if (resolved_to_const)
2636 {
2637 relocation += rel->r_addend;
2638 break;
2639 }
2640
2641 if (is_pic)
2642 {
2643 fatal = (loongarch_reloc_is_fatal
2644 (info, input_bfd, input_section, rel, howto,
2645 bfd_reloc_notsupported, is_undefweak, name,
2646 "Under PIC we don't know load address. Re-compile "
2647 "with '-fpic'?"));
2648 break;
2649 }
2650
2651 if (resolved_dynly)
2652 {
2653 if (!(plt && h && h->plt.offset != MINUS_ONE))
2654 {
2655 fatal = (loongarch_reloc_is_fatal
2656 (info, input_bfd, input_section, rel, howto,
2657 bfd_reloc_undefined, is_undefweak, name,
2658 "Can't be resolved dynamically. Try to re-compile "
2659 "with '-fpic'?"));
2660 break;
2661 }
2662
2663 if (rel->r_addend != 0)
2664 {
2665 fatal = (loongarch_reloc_is_fatal
2666 (info, input_bfd, input_section, rel, howto,
2667 bfd_reloc_notsupported, is_undefweak, name,
2668 "Shouldn't be with r_addend."));
2669 break;
2670 }
2671
2672 relocation = sec_addr (plt) + h->plt.offset;
2673 unresolved_reloc = false;
2674 break;
2675 }
2676
2677 if (resolved_local)
2678 {
2679 relocation += rel->r_addend;
2680 break;
2681 }
2682
2683 break;
2684
2685 case R_LARCH_SOP_PUSH_PCREL:
2686 case R_LARCH_SOP_PUSH_PLT_PCREL:
2687 unresolved_reloc = false;
2688
6d13722a 2689 if (is_undefweak)
e214f8db 2690 {
2691 i = 0, j = 0;
2692 relocation = 0;
2693 if (resolved_dynly)
2694 {
2695 if (h && h->plt.offset != MINUS_ONE)
2696 i = 1, j = 2;
2697 else
2698 fatal = (loongarch_reloc_is_fatal
2699 (info, input_bfd, input_section, rel, howto,
2700 bfd_reloc_dangerous, is_undefweak, name,
2701 "Undefweak need to be resolved dynamically, "
2702 "but PLT stub doesn't represent."));
2703 }
2704 }
2705 else
2706 {
2707 if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
2708 {
2709 fatal = (loongarch_reloc_is_fatal
2710 (info, input_bfd, input_section, rel, howto,
2711 bfd_reloc_undefined, is_undefweak, name,
2712 "PLT stub does not represent and "
2713 "symbol not defined."));
2714 break;
2715 }
2716
2717 if (resolved_local)
2718 i = 0, j = 2;
2719 else /* if (resolved_dynly) */
2720 {
2721 if (!(h && h->plt.offset != MINUS_ONE))
2722 fatal = (loongarch_reloc_is_fatal
2723 (info, input_bfd, input_section, rel, howto,
2724 bfd_reloc_dangerous, is_undefweak, name,
2725 "Internal: PLT stub doesn't represent. "
2726 "Resolve it with pcrel"));
2727 i = 1, j = 3;
2728 }
2729 }
2730
2731 for (; i < j; i++)
2732 {
2733 if ((i & 1) == 0 && defined_local)
2734 {
2735 relocation -= pc;
2736 relocation += rel->r_addend;
2737 break;
2738 }
2739
2740 if ((i & 1) && h && h->plt.offset != MINUS_ONE)
2741 {
2742 if (rel->r_addend != 0)
2743 {
2744 fatal = (loongarch_reloc_is_fatal
2745 (info, input_bfd, input_section, rel, howto,
2746 bfd_reloc_notsupported, is_undefweak, name,
2747 "PLT shouldn't be with r_addend."));
2748 break;
2749 }
2750 relocation = sec_addr (plt) + h->plt.offset - pc;
2751 break;
2752 }
2753 }
2754 break;
2755
2756 case R_LARCH_SOP_PUSH_GPREL:
2757 unresolved_reloc = false;
2758
2759 if (rel->r_addend != 0)
2760 {
2761 fatal = (loongarch_reloc_is_fatal
2762 (info, input_bfd, input_section, rel, howto,
2763 bfd_reloc_notsupported, is_undefweak, name,
2764 "Shouldn't be with r_addend."));
2765 break;
2766 }
2767
2768 if (h != NULL)
2769 {
6d13722a 2770 off = h->got.offset & (~1);
e214f8db 2771
6d13722a 2772 if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC)
e214f8db 2773 {
2774 fatal = (loongarch_reloc_is_fatal
2775 (info, input_bfd, input_section, rel, howto,
2776 bfd_reloc_notsupported, is_undefweak, name,
2777 "Internal: GOT entry doesn't represent."));
2778 break;
2779 }
2780
d218dba3 2781 /* Hidden symbol not has .got entry, only .got.plt entry
2782 so gprel is (plt - got). */
6d13722a 2783 if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
d218dba3 2784 {
2785 if (h->plt.offset == (bfd_vma) -1)
2786 {
2787 abort();
2788 }
2789
2790 bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE;
2791 off = plt_index * GOT_ENTRY_SIZE;
2792
2793 if (htab->elf.splt != NULL)
2794 {
2795 /* Section .plt header is 2 times of plt entry. */
6d13722a 2796 off = sec_addr (htab->elf.sgotplt) + off
2797 - sec_addr (htab->elf.sgot);
d218dba3 2798 }
2799 else
2800 {
2801 /* Section iplt not has plt header. */
6d13722a 2802 off = sec_addr (htab->elf.igotplt) + off
2803 - sec_addr (htab->elf.sgot);
d218dba3 2804 }
2805 }
2806
6d13722a 2807 if ((h->got.offset & 1) == 0)
e214f8db 2808 {
6d13722a 2809 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
2810 bfd_link_pic (info), h)
2811 && ((bfd_link_pic (info)
2812 && SYMBOL_REFERENCES_LOCAL (info, h))))
e214f8db 2813 {
6d13722a 2814 /* This is actually a static link, or it is a
2815 -Bsymbolic link and the symbol is defined
2816 locally, or the symbol was forced to be local
2817 because of a version file. We must initialize
2818 this entry in the global offset table. Since the
2819 offset must always be a multiple of the word size,
2820 we use the least significant bit to record whether
2821 we have initialized it already.
2822
2823 When doing a dynamic link, we create a rela.got
2824 relocation entry to initialize the value. This
2825 is done in the finish_dynamic_symbol routine. */
2826
2827 if (resolved_dynly)
2828 {
2829 fatal = (loongarch_reloc_is_fatal
2830 (info, input_bfd, input_section, rel, howto,
2831 bfd_reloc_dangerous, is_undefweak, name,
2832 "Internal: here shouldn't dynamic."));
2833 }
e214f8db 2834
6d13722a 2835 if (!(defined_local || resolved_to_const))
2836 {
2837 fatal = (loongarch_reloc_is_fatal
2838 (info, input_bfd, input_section, rel, howto,
2839 bfd_reloc_undefined, is_undefweak, name,
2840 "Internal: "));
2841 break;
2842 }
e214f8db 2843
6d13722a 2844 asection *s;
2845 Elf_Internal_Rela outrel;
2846 /* We need to generate a R_LARCH_RELATIVE reloc
2847 for the dynamic linker. */
2848 s = htab->elf.srelgot;
2849 if (!s)
d218dba3 2850 {
6d13722a 2851 fatal = loongarch_reloc_is_fatal
2852 (info, input_bfd,
2853 input_section, rel, howto,
2854 bfd_reloc_notsupported, is_undefweak, name,
2855 "Internal: '.rel.got' not represent");
2856 break;
d218dba3 2857 }
6d13722a 2858
2859 outrel.r_offset = sec_addr (got) + off;
2860 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2861 outrel.r_addend = relocation; /* Link-time addr. */
2862 loongarch_elf_append_rela (output_bfd, s, &outrel);
e214f8db 2863 }
6d13722a 2864 bfd_put_NN (output_bfd, relocation, got->contents + off);
2865 h->got.offset |= 1;
e214f8db 2866 }
2867 }
2868 else
2869 {
2870 if (!local_got_offsets)
2871 {
2872 fatal = (loongarch_reloc_is_fatal
2873 (info, input_bfd, input_section, rel, howto,
2874 bfd_reloc_notsupported, is_undefweak, name,
2875 "Internal: local got offsets not reporesent."));
2876 break;
2877 }
2878
6d13722a 2879 off = local_got_offsets[r_symndx] & (~1);
e214f8db 2880
6d13722a 2881 if (local_got_offsets[r_symndx] == MINUS_ONE)
e214f8db 2882 {
2883 fatal = (loongarch_reloc_is_fatal
2884 (info, input_bfd, input_section, rel, howto,
2885 bfd_reloc_notsupported, is_undefweak, name,
2886 "Internal: GOT entry doesn't represent."));
2887 break;
2888 }
2889
2890 /* The offset must always be a multiple of the word size.
2891 So, we can use the least significant bit to record
2892 whether we have already processed this entry. */
8b4d46df 2893 if ((local_got_offsets[r_symndx] & 1) == 0)
e214f8db 2894 {
2895 if (is_pic)
2896 {
2897 asection *s;
2898 Elf_Internal_Rela outrel;
2899 /* We need to generate a R_LARCH_RELATIVE reloc
2900 for the dynamic linker. */
2901 s = htab->elf.srelgot;
2902 if (!s)
2903 {
2904 fatal = (loongarch_reloc_is_fatal
2905 (info, input_bfd, input_section, rel, howto,
2906 bfd_reloc_notsupported, is_undefweak, name,
2907 "Internal: '.rel.got' not represent"));
2908 break;
2909 }
2910
2911 outrel.r_offset = sec_addr (got) + off;
2912 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2913 outrel.r_addend = relocation; /* Link-time addr. */
2914 loongarch_elf_append_rela (output_bfd, s, &outrel);
2915 }
2916
2917 bfd_put_NN (output_bfd, relocation, got->contents + off);
2918 local_got_offsets[r_symndx] |= 1;
2919 }
2920 }
2921 relocation = off;
6d13722a 2922
e214f8db 2923 break;
2924
2925 case R_LARCH_SOP_PUSH_TLS_GOT:
2926 case R_LARCH_SOP_PUSH_TLS_GD:
6d13722a 2927 {
2928 unresolved_reloc = false;
2929 if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
2930 is_ie = true;
2931
2932 bfd_vma got_off = 0;
2933 if (h != NULL)
2934 {
2935 got_off = h->got.offset;
2936 h->got.offset |= 1;
2937 }
2938 else
2939 {
2940 got_off = local_got_offsets[r_symndx];
2941 local_got_offsets[r_symndx] |= 1;
2942 }
2943
2944 BFD_ASSERT (got_off != MINUS_ONE);
2945
2946 ie_off = 0;
2947 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
2948 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
2949 ie_off = 2 * GOT_ENTRY_SIZE;
2950
2951 if ((got_off & 1) == 0)
2952 {
2953 Elf_Internal_Rela rela;
2954 asection *srel = htab->elf.srelgot;
2955 bfd_vma tls_block_off = 0;
2956
2957 if (SYMBOL_REFERENCES_LOCAL (info, h))
2958 {
2959 BFD_ASSERT (elf_hash_table (info)->tls_sec);
2960 tls_block_off = relocation
2961 - elf_hash_table (info)->tls_sec->vma;
2962 }
2963
2964 if (tls_type & GOT_TLS_GD)
2965 {
2966 rela.r_offset = sec_addr (got) + got_off;
2967 rela.r_addend = 0;
2968 if (SYMBOL_REFERENCES_LOCAL (info, h))
2969 {
2970 /* Local sym, used in exec, set module id 1. */
2971 if (bfd_link_executable (info))
2972 bfd_put_NN (output_bfd, 1, got->contents + got_off);
2973 else
2974 {
2975 rela.r_info = ELFNN_R_INFO (0,
2976 R_LARCH_TLS_DTPMODNN);
2977 loongarch_elf_append_rela (output_bfd, srel, &rela);
2978 }
2979
2980 bfd_put_NN (output_bfd, tls_block_off,
2981 got->contents + got_off + GOT_ENTRY_SIZE);
2982 }
2983 /* Dynamic resolved. */
2984 else
2985 {
2986 /* Dynamic relocate module id. */
2987 rela.r_info = ELFNN_R_INFO (h->dynindx,
2988 R_LARCH_TLS_DTPMODNN);
2989 loongarch_elf_append_rela (output_bfd, srel, &rela);
2990
2991 /* Dynamic relocate offset of block. */
2992 rela.r_offset += GOT_ENTRY_SIZE;
2993 rela.r_info = ELFNN_R_INFO (h->dynindx,
2994 R_LARCH_TLS_DTPRELNN);
2995 loongarch_elf_append_rela (output_bfd, srel, &rela);
2996 }
2997 }
2998 if (tls_type & GOT_TLS_IE)
2999 {
3000 rela.r_offset = sec_addr (got) + got_off + ie_off;
3001 if (SYMBOL_REFERENCES_LOCAL (info, h))
3002 {
3003 /* Local sym, used in exec, set module id 1. */
3004 if (!bfd_link_executable (info))
3005 {
3006 rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
3007 rela.r_addend = tls_block_off;
3008 loongarch_elf_append_rela (output_bfd, srel, &rela);
3009 }
3010
3011 bfd_put_NN (output_bfd, tls_block_off,
3012 got->contents + got_off + ie_off);
3013 }
3014 /* Dynamic resolved. */
3015 else
3016 {
3017 /* Dynamic relocate offset of block. */
3018 rela.r_info = ELFNN_R_INFO (h->dynindx,
3019 R_LARCH_TLS_TPRELNN);
3020 rela.r_addend = 0;
3021 loongarch_elf_append_rela (output_bfd, srel, &rela);
3022 }
3023 }
3024 }
3025
3026 relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0);
3027 }
3028 break;
3029
3030 /* New reloc types. */
3031 case R_LARCH_B21:
3032 case R_LARCH_B26:
3033 case R_LARCH_B16:
e214f8db 3034 unresolved_reloc = false;
6d13722a 3035 if (is_undefweak)
3036 {
3037 relocation = 0;
3038 }
e214f8db 3039
6d13722a 3040 if (resolved_local)
e214f8db 3041 {
6d13722a 3042 relocation -= pc;
3043 relocation += rel->r_addend;
3044 }
3045 else if (resolved_dynly)
3046 {
3047 BFD_ASSERT (h
3048 && (h->plt.offset != MINUS_ONE
3049 || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
3050 && rel->r_addend == 0);
3051 if (h && h->plt.offset == MINUS_ONE
3052 && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
3053 {
3054 relocation -= pc;
3055 relocation += rel->r_addend;
3056 }
3057 else
3058 relocation = sec_addr (plt) + h->plt.offset - pc;
3059 }
3060
3061 break;
3062
3063 case R_LARCH_ABS_HI20:
3064 case R_LARCH_ABS_LO12:
3065 case R_LARCH_ABS64_LO20:
3066 case R_LARCH_ABS64_HI12:
3067 BFD_ASSERT (!is_pic);
3068
3069 if (is_undefweak)
3070 {
3071 BFD_ASSERT (resolved_dynly);
3072 relocation = 0;
e214f8db 3073 break;
3074 }
6d13722a 3075 else if (resolved_to_const || resolved_local)
3076 {
3077 relocation += rel->r_addend;
3078 }
3079 else if (resolved_dynly)
3080 {
3081 unresolved_reloc = false;
3082 BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE)
3083 && rel->r_addend == 0);
3084 relocation = sec_addr (plt) + h->plt.offset;
3085 }
3086
3087 break;
3088
3089 case R_LARCH_PCALA_HI20:
3090 unresolved_reloc = false;
3091 if (h && h->plt.offset != MINUS_ONE)
3092 relocation = sec_addr (plt) + h->plt.offset;
3093 else
3094 relocation += rel->r_addend;
e214f8db 3095
6d13722a 3096 RELOCATE_CALC_PC32_HI20 (relocation, pc);
3097
3098 break;
3099
3100 case R_LARCH_PCALA_LO12:
3101 /* Not support if sym_addr in 2k page edge.
3102 pcalau12i pc_hi20 (sym_addr)
3103 ld.w/d pc_lo12 (sym_addr)
3104 ld.w/d pc_lo12 (sym_addr + x)
3105 ...
3106 can not calc correct address
3107 if sym_addr < 0x800 && sym_addr + x >= 0x800. */
3108
3109 if (h && h->plt.offset != MINUS_ONE)
3110 relocation = sec_addr (plt) + h->plt.offset;
3111 else
3112 relocation += rel->r_addend;
e214f8db 3113
27121f67
NC
3114 relocation &= 0xfff;
3115 /* Signed extend. */
3116 relocation = (relocation ^ 0x800) - 0x800;
3117
3118 /* For 2G jump, generate pcalau12i, jirl. */
3119 /* If use jirl, turns to R_LARCH_B16. */
3120 uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
3121 if ((insn & 0x4c000000) == 0x4c000000)
e214f8db 3122 {
27121f67
NC
3123 rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
3124 howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
e214f8db 3125 }
6d13722a 3126 break;
e214f8db 3127
6d13722a 3128 case R_LARCH_PCALA64_LO20:
3129 case R_LARCH_PCALA64_HI12:
3130 if (h && h->plt.offset != MINUS_ONE)
bc2a35c0 3131 relocation = sec_addr (plt) + h->plt.offset;
6d13722a 3132 else
3133 relocation += rel->r_addend;
3134
3135 RELOCATE_CALC_PC64_HI32 (relocation, pc);
3136
3137 break;
3138
3139 case R_LARCH_GOT_PC_HI20:
3140 case R_LARCH_GOT_HI20:
3141 /* Calc got offset. */
3142 {
3143 unresolved_reloc = false;
3144 BFD_ASSERT (rel->r_addend == 0);
3145
3146 bfd_vma got_off = 0;
3147 if (h != NULL)
3148 {
3149 /* GOT ref or ifunc. */
3150 BFD_ASSERT (h->got.offset != MINUS_ONE
3151 || h->type == STT_GNU_IFUNC);
3152
3153 got_off = h->got.offset & (~(bfd_vma)1);
3154 /* Hidden symbol not has got entry,
3155 * only got.plt entry so it is (plt - got). */
3156 if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
3157 {
3158 bfd_vma idx;
3159 if (htab->elf.splt != NULL)
3160 {
3161 idx = (h->plt.offset - PLT_HEADER_SIZE)
3162 / PLT_ENTRY_SIZE;
3163 got_off = sec_addr (htab->elf.sgotplt)
3164 + GOTPLT_HEADER_SIZE
3165 + (idx * GOT_ENTRY_SIZE)
3166 - sec_addr (htab->elf.sgot);
3167 }
3168 else
3169 {
3170 idx = h->plt.offset / PLT_ENTRY_SIZE;
3171 got_off = sec_addr (htab->elf.sgotplt)
3172 + (idx * GOT_ENTRY_SIZE)
3173 - sec_addr (htab->elf.sgot);
3174 }
3175 }
3176
3177 if ((h->got.offset & 1) == 0)
3178 {
3179 /* We need to generate a R_LARCH_RELATIVE reloc once
3180 * in loongarch_elf_finish_dynamic_symbol or now,
3181 * call finish_dyn && nopic
3182 * or !call finish_dyn && pic. */
3183 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
3184 bfd_link_pic (info),
3185 h)
3186 && bfd_link_pic (info)
3187 && SYMBOL_REFERENCES_LOCAL (info, h))
3188 {
3189 Elf_Internal_Rela rela;
3190 rela.r_offset = sec_addr (got) + got_off;
3191 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3192 rela.r_addend = relocation;
3193 loongarch_elf_append_rela (output_bfd,
3194 htab->elf.srelgot, &rela);
3195 }
3196 h->got.offset |= 1;
6224a6c2
XR
3197 bfd_put_NN (output_bfd, relocation,
3198 got->contents + got_off);
6d13722a 3199 }
3200 }
3201 else
3202 {
3203 BFD_ASSERT (local_got_offsets
3204 && local_got_offsets[r_symndx] != MINUS_ONE);
3205
3206 got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
3207 if ((local_got_offsets[r_symndx] & 1) == 0)
3208 {
3209 if (bfd_link_pic (info))
3210 {
3211 Elf_Internal_Rela rela;
3212 rela.r_offset = sec_addr (got) + got_off;
3213 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3214 rela.r_addend = relocation;
3215 loongarch_elf_append_rela (output_bfd,
3216 htab->elf.srelgot, &rela);
3217 }
3218 local_got_offsets[r_symndx] |= 1;
3219 }
6224a6c2 3220 bfd_put_NN (output_bfd, relocation, got->contents + got_off);
6d13722a 3221 }
3222
6d13722a 3223 relocation = got_off + sec_addr (got);
3224 }
3225
3226 if (r_type == R_LARCH_GOT_PC_HI20)
3227 RELOCATE_CALC_PC32_HI20 (relocation, pc);
3228
3229 break;
3230
3231 case R_LARCH_GOT_PC_LO12:
3232 case R_LARCH_GOT64_PC_LO20:
3233 case R_LARCH_GOT64_PC_HI12:
3234 case R_LARCH_GOT_LO12:
3235 case R_LARCH_GOT64_LO20:
3236 case R_LARCH_GOT64_HI12:
3237 {
3238 unresolved_reloc = false;
3239 bfd_vma got_off;
3240 if (h)
3241 got_off = h->got.offset & (~(bfd_vma)1);
3242 else
3243 got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
3244
3245 if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
3246 {
3247 bfd_vma idx;
3248 if (htab->elf.splt != NULL)
3249 idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
3250 else
3251 idx = h->plt.offset / PLT_ENTRY_SIZE;
3252
3253 got_off = sec_addr (htab->elf.sgotplt)
3254 + GOTPLT_HEADER_SIZE
3255 + (idx * GOT_ENTRY_SIZE)
3256 - sec_addr (htab->elf.sgot);
3257 }
3258 relocation = got_off + sec_addr (got);
3259 }
3260
3261 if (r_type == R_LARCH_GOT_PC_LO12)
3262 relocation &= (bfd_vma)0xfff;
3263 else if (r_type == R_LARCH_GOT64_PC_LO20
3264 || r_type == R_LARCH_GOT64_PC_HI12)
3265 RELOCATE_CALC_PC64_HI32 (relocation, pc);
3266
3267 break;
3268
3269 case R_LARCH_TLS_LE_HI20:
3270 case R_LARCH_TLS_LE_LO12:
3271 case R_LARCH_TLS_LE64_LO20:
3272 case R_LARCH_TLS_LE64_HI12:
3273 BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
3274
3275 relocation -= elf_hash_table (info)->tls_sec->vma;
3276 break;
3277
3278 /* TLS IE LD/GD process separately is troublesome.
3279 When a symbol is both ie and LD/GD, h->got.off |= 1
3280 make only one type be relocated. We must use
3281 h->got.offset |= 1 and h->got.offset |= 2
3282 diff IE and LD/GD. And all (got_off & (~(bfd_vma)1))
3283 (IE LD/GD and reusable GOT reloc) must change to
3284 (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
3285 as a tag.
3286 Now, LD and GD is both GOT_TLS_GD type, LD seems to
3287 can be omitted. */
3288 case R_LARCH_TLS_IE_PC_HI20:
3289 case R_LARCH_TLS_IE_HI20:
3290 case R_LARCH_TLS_LD_PC_HI20:
3291 case R_LARCH_TLS_LD_HI20:
3292 case R_LARCH_TLS_GD_PC_HI20:
3293 case R_LARCH_TLS_GD_HI20:
3294 BFD_ASSERT (rel->r_addend == 0);
3295 unresolved_reloc = false;
3296
3297 if (r_type == R_LARCH_TLS_IE_PC_HI20
3298 || r_type == R_LARCH_TLS_IE_HI20)
3299 is_ie = true;
3300
3301 bfd_vma got_off = 0;
e214f8db 3302 if (h != NULL)
3303 {
6d13722a 3304 got_off = h->got.offset;
e214f8db 3305 h->got.offset |= 1;
3306 }
3307 else
3308 {
6d13722a 3309 got_off = local_got_offsets[r_symndx];
e214f8db 3310 local_got_offsets[r_symndx] |= 1;
3311 }
3312
6d13722a 3313 BFD_ASSERT (got_off != MINUS_ONE);
e214f8db 3314
e214f8db 3315 ie_off = 0;
6d13722a 3316 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
e214f8db 3317 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3318 ie_off = 2 * GOT_ENTRY_SIZE;
3319
6d13722a 3320 if ((got_off & 1) == 0)
e214f8db 3321 {
6d13722a 3322 Elf_Internal_Rela rela;
3323 asection *relgot = htab->elf.srelgot;
e214f8db 3324 bfd_vma tls_block_off = 0;
e214f8db 3325
6d13722a 3326 if (SYMBOL_REFERENCES_LOCAL (info, h))
e214f8db 3327 {
6d13722a 3328 BFD_ASSERT (elf_hash_table (info)->tls_sec);
3329 tls_block_off = relocation
3330 - elf_hash_table (info)->tls_sec->vma;
e214f8db 3331 }
3332
3333 if (tls_type & GOT_TLS_GD)
3334 {
6d13722a 3335 rela.r_offset = sec_addr (got) + got_off;
3336 rela.r_addend = 0;
3337 if (SYMBOL_REFERENCES_LOCAL (info, h))
e214f8db 3338 {
6d13722a 3339 /* Local sym, used in exec, set module id 1. */
3340 if (bfd_link_executable (info))
3341 bfd_put_NN (output_bfd, 1, got->contents + got_off);
3342 else
3343 {
3344 rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
3345 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3346 }
e214f8db 3347
6d13722a 3348 bfd_put_NN (output_bfd, tls_block_off,
3349 got->contents + got_off + GOT_ENTRY_SIZE);
3350 }
3351 /* Dynamic resolved. */
3352 else
e214f8db 3353 {
6d13722a 3354 /* Dynamic relocate module id. */
3355 rela.r_info = ELFNN_R_INFO (h->dynindx,
3356 R_LARCH_TLS_DTPMODNN);
3357 loongarch_elf_append_rela (output_bfd, relgot, &rela);
3358
3359 /* Dynamic relocate offset of block. */
3360 rela.r_offset += GOT_ENTRY_SIZE;
3361 rela.r_info = ELFNN_R_INFO (h->dynindx,
3362 R_LARCH_TLS_DTPRELNN);
3363 loongarch_elf_append_rela (output_bfd, relgot, &rela);
e214f8db 3364 }
3365 }
e214f8db 3366 if (tls_type & GOT_TLS_IE)
3367 {
6d13722a 3368 rela.r_offset = sec_addr (got) + got_off + ie_off;
3369 if (SYMBOL_REFERENCES_LOCAL (info, h))
e214f8db 3370 {
6d13722a 3371 /* Local sym, used in exec, set module id 1. */
3372 if (!bfd_link_executable (info))
d218dba3 3373 {
6d13722a 3374 rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
3375 rela.r_addend = tls_block_off;
3376 loongarch_elf_append_rela (output_bfd, relgot, &rela);
d218dba3 3377 }
6d13722a 3378
3379 bfd_put_NN (output_bfd, tls_block_off,
3380 got->contents + got_off + ie_off);
3381 }
3382 /* Dynamic resolved. */
3383 else
3384 {
3385 /* Dynamic relocate offset of block. */
3386 rela.r_info = ELFNN_R_INFO (h->dynindx,
3387 R_LARCH_TLS_TPRELNN);
3388 rela.r_addend = 0;
3389 loongarch_elf_append_rela (output_bfd, relgot, &rela);
e214f8db 3390 }
3391 }
3392 }
6d13722a 3393 relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
3394 + (is_ie ? ie_off : 0);
3395
3396 if (r_type == R_LARCH_TLS_LD_PC_HI20
3397 || r_type == R_LARCH_TLS_GD_PC_HI20
3398 || r_type == R_LARCH_TLS_IE_PC_HI20)
3399 RELOCATE_CALC_PC32_HI20 (relocation, pc);
3400
3401 break;
3402
3403 case R_LARCH_TLS_IE_PC_LO12:
3404 case R_LARCH_TLS_IE64_PC_LO20:
3405 case R_LARCH_TLS_IE64_PC_HI12:
3406 case R_LARCH_TLS_IE_LO12:
3407 case R_LARCH_TLS_IE64_LO20:
3408 case R_LARCH_TLS_IE64_HI12:
3409 unresolved_reloc = false;
3410
3411 if (h)
3412 relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
3413 else
3414 relocation = sec_addr (got)
3415 + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
3416
3417 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
3418 /* Use both TLS_GD and TLS_IE. */
3419 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
3420 relocation += 2 * GOT_ENTRY_SIZE;
3421
3422 if (r_type == R_LARCH_TLS_IE_PC_LO12)
3423 relocation &= (bfd_vma)0xfff;
3424 else if (r_type == R_LARCH_TLS_IE64_PC_LO20
3425 || r_type == R_LARCH_TLS_IE64_PC_HI12)
3426 RELOCATE_CALC_PC64_HI32 (relocation, pc);
3427
3428 break;
e214f8db 3429
6d13722a 3430 case R_LARCH_RELAX:
e214f8db 3431 break;
3432
3433 default:
3434 break;
3435 }
3436
3437 if (fatal)
3438 break;
3439
3440 do
3441 {
3442 /* 'unresolved_reloc' means we haven't done it yet.
3443 We need help of dynamic linker to fix this memory location up. */
3444 if (!unresolved_reloc)
3445 break;
3446
3447 if (_bfd_elf_section_offset (output_bfd, info, input_section,
3448 rel->r_offset) == MINUS_ONE)
3449 /* WHY? May because it's invalid so skip checking.
6d13722a 3450 But why dynamic reloc a invalid section? */
e214f8db 3451 break;
3452
3453 if (input_section->output_section->flags & SEC_DEBUGGING)
3454 {
3455 fatal = (loongarch_reloc_is_fatal
3456 (info, input_bfd, input_section, rel, howto,
3457 bfd_reloc_dangerous, is_undefweak, name,
3458 "Seems dynamic linker not process "
3459 "sections 'SEC_DEBUGGING'."));
3460 }
3461 if (!is_dyn)
3462 break;
3463
3464 if ((info->flags & DF_TEXTREL) == 0)
3465 if (input_section->output_section->flags & SEC_READONLY)
3466 info->flags |= DF_TEXTREL;
3467 }
3468 while (0);
3469
3470 if (fatal)
3471 break;
3472
3473 loongarch_record_one_reloc (input_bfd, input_section, r_type,
3474 rel->r_offset, sym, h, rel->r_addend);
3475
3476 if (r != bfd_reloc_continue)
3477 r = perform_relocation (rel, input_section, howto, relocation,
3478 input_bfd, contents);
3479
3480 switch (r)
3481 {
3482 case bfd_reloc_dangerous:
3483 case bfd_reloc_continue:
3484 case bfd_reloc_ok:
3485 continue;
3486
3487 case bfd_reloc_overflow:
3488 /* Overflow value can't be filled in. */
3489 loongarch_dump_reloc_record (info->callbacks->info);
3490 info->callbacks->reloc_overflow
3491 (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
3492 input_bfd, input_section, rel->r_offset);
3493 break;
3494
3495 case bfd_reloc_outofrange:
3496 /* Stack state incorrect. */
3497 loongarch_dump_reloc_record (info->callbacks->info);
3498 info->callbacks->info
3499 ("%X%H: Internal stack state is incorrect.\n"
3500 "Want to push to full stack or pop from empty stack?\n",
3501 input_bfd, input_section, rel->r_offset);
3502 break;
3503
3504 case bfd_reloc_notsupported:
3505 info->callbacks->info ("%X%H: Unknown relocation type.\n", input_bfd,
3506 input_section, rel->r_offset);
3507 break;
3508
3509 default:
3510 info->callbacks->info ("%X%H: Internal: unknown error.\n", input_bfd,
3511 input_section, rel->r_offset);
3512 break;
3513 }
3514
3515 fatal = true;
e214f8db 3516 }
3517
3518 return !fatal;
3519}
3520
3521/* Finish up dynamic symbol handling. We set the contents of various
3522 dynamic sections here. */
3523
3524static bool
3525loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
3526 struct bfd_link_info *info,
3527 struct elf_link_hash_entry *h,
3528 Elf_Internal_Sym *sym)
3529{
3530 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
3531 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
ae2e4d40
XR
3532 asection *rela_dyn = bfd_get_section_by_name (output_bfd, ".rela.dyn");
3533 struct bfd_link_order *lo = NULL;
3534 Elf_Internal_Rela *slot = NULL, *last_slot = NULL;
3535
3536 if (rela_dyn)
3537 lo = rela_dyn->map_head.link_order;
e214f8db 3538
3539 if (h->plt.offset != MINUS_ONE)
3540 {
3541 size_t i, plt_idx;
d218dba3 3542 asection *plt, *gotplt, *relplt;
e214f8db 3543 bfd_vma got_address;
3544 uint32_t plt_entry[PLT_ENTRY_INSNS];
3545 bfd_byte *loc;
3546 Elf_Internal_Rela rela;
ae2e4d40 3547 asection *rela_sec = NULL;
e214f8db 3548
e214f8db 3549 if (htab->elf.splt)
3550 {
3551 BFD_ASSERT ((h->type == STT_GNU_IFUNC
3552 && SYMBOL_REFERENCES_LOCAL (info, h))
3553 || h->dynindx != -1);
3554
3555 plt = htab->elf.splt;
3556 gotplt = htab->elf.sgotplt;
bc2a35c0 3557 if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
3558 relplt = htab->elf.srelgot;
3559 else
3560 relplt = htab->elf.srelplt;
d218dba3 3561 plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
e214f8db 3562 got_address =
3563 sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
3564 }
3565 else /* if (htab->elf.iplt) */
3566 {
3567 BFD_ASSERT (h->type == STT_GNU_IFUNC
3568 && SYMBOL_REFERENCES_LOCAL (info, h));
3569
3570 plt = htab->elf.iplt;
3571 gotplt = htab->elf.igotplt;
3572 relplt = htab->elf.irelplt;
d218dba3 3573 plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
e214f8db 3574 got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
3575 }
3576
3577 /* Find out where the .plt entry should go. */
3578 loc = plt->contents + h->plt.offset;
3579
3580 /* Fill in the PLT entry itself. */
3581 if (!loongarch_make_plt_entry (got_address,
3582 sec_addr (plt) + h->plt.offset,
3583 plt_entry))
3584 return false;
3585
3586 for (i = 0; i < PLT_ENTRY_INSNS; i++)
3587 bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
3588
6d13722a 3589 /* Fill in the initial value of the got.plt entry. */
e214f8db 3590 loc = gotplt->contents + (got_address - sec_addr (gotplt));
3591 bfd_put_NN (output_bfd, sec_addr (plt), loc);
3592
3593 rela.r_offset = got_address;
d218dba3 3594
bc2a35c0 3595 /* TRUE if this is a PLT reference to a local IFUNC. */
3596 if (PLT_LOCAL_IFUNC_P (info, h)
3597 && (relplt == htab->elf.srelgot
3598 || relplt == htab->elf.irelplt))
3599 {
ae2e4d40
XR
3600 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
3601 rela.r_addend = (h->root.u.def.value
bc2a35c0 3602 + h->root.u.def.section->output_section->vma
3603 + h->root.u.def.section->output_offset);
bc2a35c0 3604
ae2e4d40
XR
3605 /* Find the space after dyn sort. */
3606 while (slot == last_slot || slot->r_offset != 0)
bc2a35c0 3607 {
ae2e4d40 3608 if (slot != last_slot)
bc2a35c0 3609 {
ae2e4d40
XR
3610 slot++;
3611 continue;
bc2a35c0 3612 }
ae2e4d40
XR
3613
3614 BFD_ASSERT (lo != NULL);
3615 rela_sec = lo->u.indirect.section;
3616 lo = lo->next;
3617
3618 slot = (Elf_Internal_Rela *)rela_sec->contents;
3619 last_slot = (Elf_Internal_Rela *)(rela_sec->contents +
3620 rela_sec->size);
bc2a35c0 3621 }
3622
ae2e4d40
XR
3623 bed->s->swap_reloca_out (output_bfd, &rela, (bfd_byte *)slot);
3624 rela_sec->reloc_count++;
bc2a35c0 3625 }
3626 else
3627 {
3628 /* Fill in the entry in the rela.plt section. */
3629 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
3630 rela.r_addend = 0;
3631 loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
3632 bed->s->swap_reloca_out (output_bfd, &rela, loc);
3633 }
e214f8db 3634
3635 if (!h->def_regular)
3636 {
3637 /* Mark the symbol as undefined, rather than as defined in
3638 the .plt section. Leave the value alone. */
3639 sym->st_shndx = SHN_UNDEF;
3640 /* If the symbol is weak, we do need to clear the value.
3641 Otherwise, the PLT entry would provide a definition for
3642 the symbol even if the symbol wasn't defined anywhere,
3643 and so the symbol would never be NULL. */
3644 if (!h->ref_regular_nonweak)
3645 sym->st_value = 0;
3646 }
3647 }
3648
3649 if (h->got.offset != MINUS_ONE
3650 /* TLS got entry have been handled in elf_relocate_section. */
3651 && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
6d13722a 3652 /* Have allocated got entry but not allocated rela before. */
e214f8db 3653 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
3654 {
3655 asection *sgot, *srela;
3656 Elf_Internal_Rela rela;
6d13722a 3657 bfd_vma off = h->got.offset & ~(bfd_vma)1;
e214f8db 3658
3659 /* This symbol has an entry in the GOT. Set it up. */
e214f8db 3660 sgot = htab->elf.sgot;
3661 srela = htab->elf.srelgot;
3662 BFD_ASSERT (sgot && srela);
3663
3664 rela.r_offset = sec_addr (sgot) + off;
3665
d218dba3 3666 if (h->def_regular
3667 && h->type == STT_GNU_IFUNC)
e214f8db 3668 {
d218dba3 3669 if(h->plt.offset == MINUS_ONE)
3670 {
3671 if (htab->elf.splt == NULL)
3672 srela = htab->elf.irelplt;
3673
3674 if (SYMBOL_REFERENCES_LOCAL (info, h))
3675 {
3676 asection *sec = h->root.u.def.section;
3677 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
3678 rela.r_addend = h->root.u.def.value + sec->output_section->vma
3679 + sec->output_offset;
3680 bfd_put_NN (output_bfd, 0, sgot->contents + off);
3681 }
3682 else
3683 {
d218dba3 3684 BFD_ASSERT (h->dynindx != -1);
3685 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
3686 rela.r_addend = 0;
3687 bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off);
3688 }
3689 }
3690 else if(bfd_link_pic (info))
e214f8db 3691 {
d218dba3 3692 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
3693 rela.r_addend = 0;
3694 bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
e214f8db 3695 }
3696 else
3697 {
d218dba3 3698 asection *plt;
3699 /* For non-shared object, we can't use .got.plt, which
3700 contains the real function address if we need pointer
3701 equality. We load the GOT entry with the PLT entry. */
3702 plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
3703 bfd_put_NN (output_bfd,
3704 (plt->output_section->vma
3705 + plt->output_offset
3706 + h->plt.offset),
3707 sgot->contents + off);
3708 return true;
e214f8db 3709 }
3710 }
3711 else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
3712 {
e214f8db 3713 asection *sec = h->root.u.def.section;
3714 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
3715 rela.r_addend = (h->root.u.def.value + sec->output_section->vma
3716 + sec->output_offset);
3717 }
3718 else
3719 {
e214f8db 3720 BFD_ASSERT (h->dynindx != -1);
3721 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
3722 rela.r_addend = 0;
3723 }
3724
3725 loongarch_elf_append_rela (output_bfd, srela, &rela);
3726 }
3727
e214f8db 3728 /* Mark some specially defined symbols as absolute. */
3729 if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
3730 sym->st_shndx = SHN_ABS;
3731
3732 return true;
3733}
3734
3735/* Finish up the dynamic sections. */
3736
3737static bool
3738loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
3739 asection *sdyn)
3740{
3741 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
3742 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
3743 size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
3744 bfd_byte *dyncon, *dynconend;
3745
3746 dynconend = sdyn->contents + sdyn->size;
3747 for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
3748 {
3749 Elf_Internal_Dyn dyn;
3750 asection *s;
3751 int skipped = 0;
3752
3753 bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
3754
3755 switch (dyn.d_tag)
3756 {
3757 case DT_PLTGOT:
3758 s = htab->elf.sgotplt;
3759 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3760 break;
3761 case DT_JMPREL:
3762 s = htab->elf.srelplt;
3763 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3764 break;
3765 case DT_PLTRELSZ:
3766 s = htab->elf.srelplt;
3767 dyn.d_un.d_val = s->size;
3768 break;
3769 case DT_TEXTREL:
3770 if ((info->flags & DF_TEXTREL) == 0)
3771 skipped = 1;
3772 break;
3773 case DT_FLAGS:
3774 if ((info->flags & DF_TEXTREL) == 0)
3775 dyn.d_un.d_val &= ~DF_TEXTREL;
3776 break;
3777 }
3778 if (skipped)
3779 skipped_size += dynsize;
3780 else
3781 bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
3782 }
3783 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
3784 memset (dyncon - skipped_size, 0, skipped_size);
3785 return true;
3786}
3787
3788/* Finish up local dynamic symbol handling. We set the contents of
3789 various dynamic sections here. */
3790
3791static bool
3792elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
3793{
3794 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
3795 struct bfd_link_info *info = (struct bfd_link_info *) inf;
3796
3797 return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
3798}
3799
3800static bool
3801loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
3802 struct bfd_link_info *info)
3803{
3804 bfd *dynobj;
3805 asection *sdyn, *plt, *gotplt = NULL;
3806 struct loongarch_elf_link_hash_table *htab;
3807
3808 htab = loongarch_elf_hash_table (info);
3809 BFD_ASSERT (htab);
3810 dynobj = htab->elf.dynobj;
3811 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
3812
3813 if (elf_hash_table (info)->dynamic_sections_created)
3814 {
3815 BFD_ASSERT (htab->elf.splt && sdyn);
3816
3817 if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
3818 return false;
3819 }
3820
d218dba3 3821 plt = htab->elf.splt;
3822 gotplt = htab->elf.sgotplt;
e214f8db 3823
3824 if (plt && 0 < plt->size)
3825 {
3826 size_t i;
3827 uint32_t plt_header[PLT_HEADER_INSNS];
3828 if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
3829 plt_header))
3830 return false;
3831
3832 for (i = 0; i < PLT_HEADER_INSNS; i++)
3833 bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
3834
3835 elf_section_data (plt->output_section)->this_hdr.sh_entsize =
3836 PLT_ENTRY_SIZE;
3837 }
3838
3839 if (htab->elf.sgotplt)
3840 {
3841 asection *output_section = htab->elf.sgotplt->output_section;
3842
3843 if (bfd_is_abs_section (output_section))
3844 {
3845 _bfd_error_handler (_("discarded output section: `%pA'"),
3846 htab->elf.sgotplt);
3847 return false;
3848 }
3849
3850 if (0 < htab->elf.sgotplt->size)
3851 {
3852 /* Write the first two entries in .got.plt, needed for the dynamic
3853 linker. */
3854 bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
3855
3856 bfd_put_NN (output_bfd, (bfd_vma) 0,
3857 htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
3858 }
3859
3860 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
3861 }
3862
3863 if (htab->elf.sgot)
3864 {
3865 asection *output_section = htab->elf.sgot->output_section;
3866
3867 if (0 < htab->elf.sgot->size)
3868 {
3869 /* Set the first entry in the global offset table to the address of
3870 the dynamic section. */
3871 bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
3872 bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
3873 }
3874
3875 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
3876 }
3877
3878 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
3879 htab_traverse (htab->loc_hash_table,
3880 (void *) elfNN_loongarch_finish_local_dynamic_symbol, info);
3881
3882 return true;
3883}
3884
3885/* Return address for Ith PLT stub in section PLT, for relocation REL
3886 or (bfd_vma) -1 if it should not be included. */
3887
3888static bfd_vma
3889loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
3890 const arelent *rel ATTRIBUTE_UNUSED)
3891{
3892 return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
3893}
3894
3895static enum elf_reloc_type_class
3896loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
3897 const asection *rel_sec ATTRIBUTE_UNUSED,
3898 const Elf_Internal_Rela *rela)
3899{
3900 struct loongarch_elf_link_hash_table *htab;
3901 htab = loongarch_elf_hash_table (info);
3902
3903 if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
3904 {
3905 /* Check relocation against STT_GNU_IFUNC symbol if there are
3906 dynamic symbols. */
3907 bfd *abfd = info->output_bfd;
3908 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
3909 unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
3910 if (r_symndx != STN_UNDEF)
3911 {
3912 Elf_Internal_Sym sym;
3913 if (!bed->s->swap_symbol_in (abfd,
3914 htab->elf.dynsym->contents
3915 + r_symndx * bed->s->sizeof_sym,
3916 0, &sym))
3917 {
3918 /* xgettext:c-format */
3919 _bfd_error_handler (_("%pB symbol number %lu references"
3920 " nonexistent SHT_SYMTAB_SHNDX section"),
3921 abfd, r_symndx);
3922 /* Ideally an error class should be returned here. */
3923 }
3924 else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
3925 return reloc_class_ifunc;
3926 }
3927 }
3928
3929 switch (ELFNN_R_TYPE (rela->r_info))
3930 {
3931 case R_LARCH_IRELATIVE:
3932 return reloc_class_ifunc;
3933 case R_LARCH_RELATIVE:
3934 return reloc_class_relative;
3935 case R_LARCH_JUMP_SLOT:
3936 return reloc_class_plt;
3937 case R_LARCH_COPY:
3938 return reloc_class_copy;
3939 default:
3940 return reloc_class_normal;
3941 }
3942}
3943
3944/* Copy the extra info we tack onto an elf_link_hash_entry. */
3945
3946static void
3947loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
3948 struct elf_link_hash_entry *dir,
3949 struct elf_link_hash_entry *ind)
3950{
d218dba3 3951 struct elf_link_hash_entry *edir, *eind;
e214f8db 3952
d218dba3 3953 edir = dir;
3954 eind = ind;
e214f8db 3955
3956 if (eind->dyn_relocs != NULL)
3957 {
3958 if (edir->dyn_relocs != NULL)
3959 {
3960 struct elf_dyn_relocs **pp;
3961 struct elf_dyn_relocs *p;
3962
3963 /* Add reloc counts against the indirect sym to the direct sym
3964 list. Merge any entries against the same section. */
3965 for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
3966 {
3967 struct elf_dyn_relocs *q;
3968
3969 for (q = edir->dyn_relocs; q != NULL; q = q->next)
3970 if (q->sec == p->sec)
3971 {
3972 q->pc_count += p->pc_count;
3973 q->count += p->count;
3974 *pp = p->next;
3975 break;
3976 }
3977 if (q == NULL)
3978 pp = &p->next;
3979 }
3980 *pp = edir->dyn_relocs;
3981 }
3982
3983 edir->dyn_relocs = eind->dyn_relocs;
3984 eind->dyn_relocs = NULL;
3985 }
3986
3987 if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
3988 {
d218dba3 3989 loongarch_elf_hash_entry(edir)->tls_type
3990 = loongarch_elf_hash_entry(eind)->tls_type;
3991 loongarch_elf_hash_entry(eind)->tls_type = GOT_UNKNOWN;
e214f8db 3992 }
3993 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3994}
3995
3996#define PRSTATUS_SIZE 0x1d8
3997#define PRSTATUS_OFFSET_PR_CURSIG 0xc
3998#define PRSTATUS_OFFSET_PR_PID 0x20
3999#define ELF_GREGSET_T_SIZE 0x168
4000#define PRSTATUS_OFFSET_PR_REG 0x70
4001
4002/* Support for core dump NOTE sections. */
4003
4004static bool
4005loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
4006{
4007 switch (note->descsz)
4008 {
4009 default:
4010 return false;
4011
4012 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
4013 case PRSTATUS_SIZE:
4014 /* pr_cursig */
4015 elf_tdata (abfd)->core->signal =
4016 bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
4017
4018 /* pr_pid */
4019 elf_tdata (abfd)->core->lwpid =
4020 bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
4021 break;
4022 }
4023
4024 /* Make a ".reg/999" section. */
4025 return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
4026 note->descpos
4027 + PRSTATUS_OFFSET_PR_REG);
4028}
4029
4030#define PRPSINFO_SIZE 0x88
4031#define PRPSINFO_OFFSET_PR_PID 0x18
4032#define PRPSINFO_OFFSET_PR_FNAME 0x28
4033#define PRPSINFO_SIZEOF_PR_FNAME 0x10
4034#define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
4035#define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
4036
e214f8db 4037static bool
4038loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
4039{
4040 switch (note->descsz)
4041 {
4042 default:
4043 return false;
4044
4045 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
4046 case PRPSINFO_SIZE:
4047 /* pr_pid */
4048 elf_tdata (abfd)->core->pid =
4049 bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
4050
4051 /* pr_fname */
4052 elf_tdata (abfd)->core->program =
4053 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
4054 PRPSINFO_SIZEOF_PR_FNAME);
4055
4056 /* pr_psargs */
4057 elf_tdata (abfd)->core->command =
4058 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
4059 PRPSINFO_SIZEOF_PR_PS_ARGS);
4060 break;
4061 }
4062
4063 /* Note that for some reason, a spurious space is tacked
4064 onto the end of the args in some (at least one anyway)
4065 implementations, so strip it off if it exists. */
4066
4067 {
4068 char *command = elf_tdata (abfd)->core->command;
4069 int n = strlen (command);
4070
4071 if (0 < n && command[n - 1] == ' ')
4072 command[n - 1] = '\0';
4073 }
4074
4075 return true;
4076}
4077
4078/* Set the right mach type. */
4079static bool
4080loongarch_elf_object_p (bfd *abfd)
4081{
4082 /* There are only two mach types in LoongArch currently. */
4083 if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
4084 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
4085 else
4086 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
4087 return true;
4088}
4089
4090static asection *
4091loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
4092 Elf_Internal_Rela *rel,
4093 struct elf_link_hash_entry *h,
4094 Elf_Internal_Sym *sym)
4095{
4096 if (h != NULL)
4097 switch (ELFNN_R_TYPE (rel->r_info))
4098 {
4099 case R_LARCH_GNU_VTINHERIT:
4100 case R_LARCH_GNU_VTENTRY:
4101 return NULL;
4102 }
4103
4104 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
4105}
4106
e6f601b7 4107/* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For
4108 executable PLT slots where the executable never takes the address of those
4109 functions, the function symbols are not added to the hash table. */
4110
4111static bool
4112elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
4113{
4114 if (h->plt.offset != (bfd_vma) -1
4115 && !h->def_regular
4116 && !h->pointer_equality_needed)
4117 return false;
4118
4119 return _bfd_elf_hash_symbol (h);
4120}
4121
e214f8db 4122#define TARGET_LITTLE_SYM loongarch_elfNN_vec
4123#define TARGET_LITTLE_NAME "elfNN-loongarch"
4124#define ELF_ARCH bfd_arch_loongarch
4125#define ELF_TARGET_ID LARCH_ELF_DATA
4126#define ELF_MACHINE_CODE EM_LOONGARCH
4127#define ELF_MAXPAGESIZE 0x4000
4128#define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
4129#define bfd_elfNN_bfd_link_hash_table_create \
4130 loongarch_elf_link_hash_table_create
4131#define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
4132#define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
4133#define elf_info_to_howto loongarch_info_to_howto_rela
4134#define bfd_elfNN_bfd_merge_private_bfd_data \
4135 elfNN_loongarch_merge_private_bfd_data
4136
4137#define elf_backend_reloc_type_class loongarch_reloc_type_class
4138#define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
4139#define elf_backend_create_dynamic_sections \
4140 loongarch_elf_create_dynamic_sections
4141#define elf_backend_check_relocs loongarch_elf_check_relocs
4142#define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
4143#define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
4144#define elf_backend_relocate_section loongarch_elf_relocate_section
4145#define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
4146#define elf_backend_finish_dynamic_sections \
4147 loongarch_elf_finish_dynamic_sections
4148#define elf_backend_object_p loongarch_elf_object_p
4149#define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
4150#define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
4151#define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
4152#define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
e6f601b7 4153#define elf_backend_hash_symbol elf_loongarch64_hash_symbol
e214f8db 4154
4155#include "elfNN-target.h"