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