]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elfnn-loongarch.c
LoongArch: Update ABI eflag in elf header.
[thirdparty/binutils-gdb.git] / bfd / elfnn-loongarch.c
CommitLineData
e214f8db 1/* LoongArch-specific support for NN-bit ELF.
a2c58332 2 Copyright (C) 2021-2022 Free Software Foundation, Inc.
e214f8db 3 Contributed by Loongson Ltd.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
20
21#include "ansidecl.h"
22#include "sysdep.h"
23#include "bfd.h"
24#include "libbfd.h"
25#define ARCH_SIZE NN
26#include "elf-bfd.h"
27#include "objalloc.h"
28#include "elf/loongarch.h"
29#include "elfxx-loongarch.h"
30
31static bool
32loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
33 Elf_Internal_Rela *dst)
34{
35 cache_ptr->howto = loongarch_elf_rtype_to_howto (abfd,
36 ELFNN_R_TYPE (dst->r_info));
37 return cache_ptr->howto != NULL;
38}
39
40/* LoongArch ELF linker hash entry. */
41struct loongarch_elf_link_hash_entry
42{
43 struct elf_link_hash_entry elf;
44
45 /* Track dynamic relocs copied for this symbol. */
46 struct elf_dyn_relocs *dyn_relocs;
47
48#define GOT_UNKNOWN 0
49#define GOT_NORMAL 1
50#define GOT_TLS_GD 2
51#define GOT_TLS_IE 4
52#define GOT_TLS_LE 8
53 char tls_type;
54};
55
56#define loongarch_elf_hash_entry(ent) \
57 ((struct loongarch_elf_link_hash_entry *) (ent))
58
59struct _bfd_loongarch_elf_obj_tdata
60{
61 struct elf_obj_tdata root;
62
63 /* The tls_type for each local got entry. */
64 char *local_got_tls_type;
65};
66
67#define _bfd_loongarch_elf_tdata(abfd) \
68 ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
69
70#define _bfd_loongarch_elf_local_got_tls_type(abfd) \
71 (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
72
73#define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
74 (*((h) != NULL \
75 ? &loongarch_elf_hash_entry (h)->tls_type \
76 : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
77
78#define is_loongarch_elf(bfd) \
79 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
80 && elf_tdata (bfd) != NULL \
81 && elf_object_id (bfd) == LARCH_ELF_DATA)
82
83struct loongarch_elf_link_hash_table
84{
85 struct elf_link_hash_table elf;
86
87 /* Short-cuts to get to dynamic linker sections. */
88 asection *sdyntdata;
89
90 /* Small local sym to section mapping cache. */
91 struct sym_cache sym_cache;
92
93 /* Used by local STT_GNU_IFUNC symbols. */
94 htab_t loc_hash_table;
95 void *loc_hash_memory;
96
97 /* The max alignment of output sections. */
98 bfd_vma max_alignment;
99};
100
101/* Get the LoongArch ELF linker hash table from a link_info structure. */
102#define loongarch_elf_hash_table(p) \
103 (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
104 ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
105 : NULL)
106
107#define MINUS_ONE ((bfd_vma) 0 - 1)
108
109#define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
110
111#define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
112#define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
113
114#define PLT_HEADER_INSNS 8
115#define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
116
117#define PLT_ENTRY_INSNS 4
118#define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
119
120#define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
121
122#define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
123
124#define elf_backend_want_got_plt 1
125
126#define elf_backend_plt_readonly 1
127
128#define elf_backend_want_plt_sym 0
129#define elf_backend_plt_alignment 4
130#define elf_backend_can_gc_sections 1
131/* #define elf_backend_can_refcount 1 */
132#define elf_backend_want_got_sym 1
133
134#define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
135
136#define elf_backend_want_dynrelro 1
137/* #define elf_backend_rela_normal 1
138#define elf_backend_default_execstack 0 */
139
140/* Generate a PLT header. */
141
142static bool
143loongarch_make_plt_header (bfd_vma got_plt_addr, bfd_vma plt_header_addr,
144 uint32_t *entry)
145{
146 bfd_vma pcrel = got_plt_addr - plt_header_addr;
147 bfd_vma hi, lo;
148
149 if (pcrel + 0x80000800 > 0xffffffff)
150 {
151 _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
152 bfd_set_error (bfd_error_bad_value);
153 return false;
154 }
155 hi = ((pcrel + 0x800) >> 12) & 0xfffff;
156 lo = pcrel & 0xfff;
157
158 /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
159 sub.[wd] $t1, $t1, $t3
160 ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
161 addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
162 addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
163 srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
164 ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
165 jirl $r0, $t3, 0 */
166
167 if (GOT_ENTRY_SIZE == 8)
168 {
169 entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
170 entry[1] = 0x0011bdad;
171 entry[2] = 0x28c001cf | (lo & 0xfff) << 10;
172 entry[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
173 entry[4] = 0x02c001cc | (lo & 0xfff) << 10;
174 entry[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
175 entry[6] = 0x28c0018c | GOT_ENTRY_SIZE << 10;
176 entry[7] = 0x4c0001e0;
177 }
178 else
179 {
180 entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
181 entry[1] = 0x00113dad;
182 entry[2] = 0x288001cf | (lo & 0xfff) << 10;
183 entry[3] = 0x028001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
184 entry[4] = 0x028001cc | (lo & 0xfff) << 10;
185 entry[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
186 entry[6] = 0x2880018c | GOT_ENTRY_SIZE << 10;
187 entry[7] = 0x4c0001e0;
188 }
189 return true;
190}
191
192/* Generate a PLT entry. */
193
194static bool
195loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, bfd_vma plt_entry_addr,
196 uint32_t *entry)
197{
198 bfd_vma pcrel = got_plt_entry_addr - plt_entry_addr;
199 bfd_vma hi, lo;
200
201 if (pcrel + 0x80000800 > 0xffffffff)
202 {
203 _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
204 bfd_set_error (bfd_error_bad_value);
205 return false;
206 }
207 hi = ((pcrel + 0x800) >> 12) & 0xfffff;
208 lo = pcrel & 0xfff;
209
210 entry[0] = 0x1c00000f | (hi & 0xfffff) << 5;
211 entry[1] = ((GOT_ENTRY_SIZE == 8 ? 0x28c001ef : 0x288001ef)
212 | (lo & 0xfff) << 10);
213 entry[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
214 entry[3] = 0x03400000; /* nop */
215
216 return true;
217}
218
219/* Create an entry in an LoongArch ELF linker hash table. */
220
221static struct bfd_hash_entry *
222link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
223 const char *string)
224{
225 struct loongarch_elf_link_hash_entry *eh;
226
227 /* Allocate the structure if it has not already been allocated by a
228 subclass. */
229 if (entry == NULL)
230 {
231 entry = bfd_hash_allocate (table, sizeof (*eh));
232 if (entry == NULL)
233 return entry;
234 }
235
236 /* Call the allocation method of the superclass. */
237 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
238 if (entry != NULL)
239 {
240 eh = (struct loongarch_elf_link_hash_entry *) entry;
241 eh->dyn_relocs = NULL;
242 eh->tls_type = GOT_UNKNOWN;
243 }
244
245 return entry;
246}
247
248/* Compute a hash of a local hash entry. We use elf_link_hash_entry
249 for local symbol so that we can handle local STT_GNU_IFUNC symbols
250 as global symbol. We reuse indx and dynstr_index for local symbol
251 hash since they aren't used by global symbols in this backend. */
252
253static hashval_t
254elfNN_loongarch_local_htab_hash (const void *ptr)
255{
256 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr;
257 return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
258}
259
260/* Compare local hash entries. */
261
262static int
263elfNN_loongarch_local_htab_eq (const void *ptr1, const void *ptr2)
264{
265 struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1;
266 struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2;
267
268 return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
269}
270
271/* Find and/or create a hash entry for local symbol. */
272static struct elf_link_hash_entry *
273elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table *htab,
274 bfd *abfd, const Elf_Internal_Rela *rel,
275 bool create)
276{
277 struct loongarch_elf_link_hash_entry e, *ret;
278 asection *sec = abfd->sections;
279 hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, ELFNN_R_SYM (rel->r_info));
280 void **slot;
281
282 e.elf.indx = sec->id;
283 e.elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
284 slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
285 create ? INSERT : NO_INSERT);
286
287 if (!slot)
288 return NULL;
289
290 if (*slot)
291 {
292 ret = (struct loongarch_elf_link_hash_entry *) *slot;
293 return &ret->elf;
294 }
295
296 ret = ((struct loongarch_elf_link_hash_entry *)
297 objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
298 sizeof (struct loongarch_elf_link_hash_entry)));
299 if (ret)
300 {
301 memset (ret, 0, sizeof (*ret));
302 ret->elf.indx = sec->id;
303 ret->elf.pointer_equality_needed = 0;
304 ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
305 ret->elf.dynindx = -1;
306 ret->elf.needs_plt = 0;
307 ret->elf.plt.refcount = -1;
308 ret->elf.got.refcount = -1;
309 ret->elf.def_dynamic = 0;
310 ret->elf.def_regular = 1;
311 ret->elf.ref_dynamic = 0; /* This should be always 0 for local. */
312 ret->elf.ref_regular = 0;
313 ret->elf.forced_local = 1;
314 ret->elf.root.type = bfd_link_hash_defined;
315 *slot = ret;
316 }
317 return &ret->elf;
318}
319
320/* Destroy an LoongArch elf linker hash table. */
321
322static void
323elfNN_loongarch_link_hash_table_free (bfd *obfd)
324{
325 struct loongarch_elf_link_hash_table *ret;
326 ret = (struct loongarch_elf_link_hash_table *) obfd->link.hash;
327
328 if (ret->loc_hash_table)
329 htab_delete (ret->loc_hash_table);
330 if (ret->loc_hash_memory)
331 objalloc_free ((struct objalloc *) ret->loc_hash_memory);
332
333 _bfd_elf_link_hash_table_free (obfd);
334}
335
336/* Create a LoongArch ELF linker hash table. */
337
338static struct bfd_link_hash_table *
339loongarch_elf_link_hash_table_create (bfd *abfd)
340{
341 struct loongarch_elf_link_hash_table *ret;
342 bfd_size_type amt = sizeof (struct loongarch_elf_link_hash_table);
343
344 ret = (struct loongarch_elf_link_hash_table *) bfd_zmalloc (amt);
345 if (ret == NULL)
346 return NULL;
347
348 if (!_bfd_elf_link_hash_table_init
349 (&ret->elf, abfd, link_hash_newfunc,
350 sizeof (struct loongarch_elf_link_hash_entry), LARCH_ELF_DATA))
351 {
352 free (ret);
353 return NULL;
354 }
355
356 ret->max_alignment = MINUS_ONE;
357
358 ret->loc_hash_table = htab_try_create (1024, elfNN_loongarch_local_htab_hash,
359 elfNN_loongarch_local_htab_eq, NULL);
360 ret->loc_hash_memory = objalloc_create ();
361 if (!ret->loc_hash_table || !ret->loc_hash_memory)
362 {
363 elfNN_loongarch_link_hash_table_free (abfd);
364 return NULL;
365 }
366 ret->elf.root.hash_table_free = elfNN_loongarch_link_hash_table_free;
367
368 return &ret->elf.root;
369}
370
371/* Merge backend specific data from an object file to the output
372 object file when linking. */
373
374static bool
375elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
376{
377 bfd *obfd = info->output_bfd;
378 flagword in_flags = elf_elfheader (ibfd)->e_flags;
379 flagword out_flags = elf_elfheader (obfd)->e_flags;
380
381 if (!is_loongarch_elf (ibfd) || !is_loongarch_elf (obfd))
382 return true;
383
384 if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
385 {
386 _bfd_error_handler (_("%pB: ABI is incompatible with that of "
387 "the selected emulation:\n"
388 " target emulation `%s' does not match `%s'"),
389 ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
390 return false;
391 }
392
393 if (!_bfd_elf_merge_object_attributes (ibfd, info))
394 return false;
395
396 if (!elf_flags_init (obfd))
397 {
398 elf_flags_init (obfd) = true;
399 elf_elfheader (obfd)->e_flags = in_flags;
400 return true;
401 }
402
403 /* Disallow linking different ABIs. */
3b14682a 404 if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
e214f8db 405 {
406 _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd);
407 goto fail;
408 }
409
410 return true;
411
412 fail:
413 bfd_set_error (bfd_error_bad_value);
414 return false;
415}
416
417/* Create the .got section. */
418
419static bool
420loongarch_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
421{
422 flagword flags;
423 char *name;
424 asection *s, *s_got;
425 struct elf_link_hash_entry *h;
426 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
427 struct elf_link_hash_table *htab = elf_hash_table (info);
428
429 /* This function may be called more than once. */
430 if (htab->sgot != NULL)
431 return true;
432
433 flags = bed->dynamic_sec_flags;
434 name = bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got";
435 s = bfd_make_section_anyway_with_flags (abfd, name, flags | SEC_READONLY);
436
437 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
438 return false;
439 htab->srelgot = s;
440
441 s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
442 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
443 return false;
444 htab->sgot = s;
445
446 /* The first bit of the global offset table is the header. */
447 s->size += bed->got_header_size;
448
449 if (bed->want_got_plt)
450 {
451 s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
452 if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
453 return false;
454 htab->sgotplt = s;
455
456 /* Reserve room for the header. */
457 s->size = GOTPLT_HEADER_SIZE;
458 }
459
460 if (bed->want_got_sym)
461 {
462 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
463 section. We don't do this in the linker script because we don't want
464 to define the symbol if we are not creating a global offset table. */
465 h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
466 "_GLOBAL_OFFSET_TABLE_");
467 elf_hash_table (info)->hgot = h;
468 if (h == NULL)
469 return false;
470 }
471 return true;
472}
473
474/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
475 .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
476 hash table. */
477
478static bool
479loongarch_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
480{
481 struct loongarch_elf_link_hash_table *htab;
482
483 htab = loongarch_elf_hash_table (info);
484 BFD_ASSERT (htab != NULL);
485
486 if (!loongarch_elf_create_got_section (dynobj, info))
487 return false;
488
489 if (!_bfd_elf_create_dynamic_sections (dynobj, info))
490 return false;
491
492 if (!bfd_link_pic (info))
493 htab->sdyntdata
494 = bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
495 SEC_ALLOC | SEC_THREAD_LOCAL);
496
497 if (!htab->elf.splt || !htab->elf.srelplt || !htab->elf.sdynbss
498 || (!bfd_link_pic (info) && (!htab->elf.srelbss || !htab->sdyntdata)))
499 abort ();
500
501 return true;
502}
503
504static bool
505loongarch_elf_record_tls_and_got_reference (bfd *abfd,
506 struct bfd_link_info *info,
507 struct elf_link_hash_entry *h,
508 unsigned long symndx,
509 char tls_type)
510{
511 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
512 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
513
514 /* This is a global offset table entry for a local symbol. */
515 if (elf_local_got_refcounts (abfd) == NULL)
516 {
517 bfd_size_type size =
518 symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (tls_type));
519 if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
520 return false;
521 _bfd_loongarch_elf_local_got_tls_type (abfd) =
522 (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
523 }
524
525 switch (tls_type)
526 {
527 case GOT_NORMAL:
528 case GOT_TLS_GD:
529 case GOT_TLS_IE:
530 /* Need GOT. */
531 if (htab->elf.sgot == NULL
532 && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
533 return false;
534 if (h)
535 {
536 if (h->got.refcount < 0)
537 h->got.refcount = 0;
538 h->got.refcount++;
539 }
540 else
541 elf_local_got_refcounts (abfd)[symndx]++;
542 break;
543 case GOT_TLS_LE:
544 /* No need for GOT. */
545 break;
546 default:
547 _bfd_error_handler (_("Internal error: unreachable."));
548 return false;
549 }
550
551 char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
552 *new_tls_type |= tls_type;
553 if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
554 {
555 _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
556 "thread local symbol"),
557 abfd,
558 h ? h->root.root.string : "<local>");
559 return false;
560 }
561
562 return true;
563}
564
565/* Look through the relocs for a section during the first phase, and
566 allocate space in the global offset table or procedure linkage
567 table. */
568
569static bool
570loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
571 asection *sec, const Elf_Internal_Rela *relocs)
572{
573 struct loongarch_elf_link_hash_table *htab;
574 Elf_Internal_Shdr *symtab_hdr;
575 struct elf_link_hash_entry **sym_hashes;
576 const Elf_Internal_Rela *rel;
577 asection *sreloc = NULL;
578
579 if (bfd_link_relocatable (info))
580 return true;
581
582 htab = loongarch_elf_hash_table (info);
583 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
584 sym_hashes = elf_sym_hashes (abfd);
585
586 if (htab->elf.dynobj == NULL)
587 htab->elf.dynobj = abfd;
588
589 for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
590 {
591 unsigned int r_type;
592 unsigned int r_symndx;
593 struct elf_link_hash_entry *h;
594 Elf_Internal_Sym *isym = NULL;
595
596 int need_dynreloc;
597 int only_need_pcrel;
598
599 r_symndx = ELFNN_R_SYM (rel->r_info);
600 r_type = ELFNN_R_TYPE (rel->r_info);
601
602 if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
603 {
604 _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx);
605 return false;
606 }
607
608 if (r_symndx < symtab_hdr->sh_info)
609 {
610 /* A local symbol. */
611 isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx);
612 if (isym == NULL)
613 return false;
614
615 if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
616 {
617 h = elfNN_loongarch_get_local_sym_hash (htab, abfd, rel, true);
618 if (h == NULL)
619 return false;
620
621 h->type = STT_GNU_IFUNC;
622 h->ref_regular = 1;
623 }
624 else
625 h = NULL;
626 }
627 else
628 {
629 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
630 while (h->root.type == bfd_link_hash_indirect
631 || h->root.type == bfd_link_hash_warning)
632 h = (struct elf_link_hash_entry *) h->root.u.i.link;
633 }
634
635 if (h && h->type == STT_GNU_IFUNC)
636 {
637 if (htab->elf.dynobj == NULL)
638 htab->elf.dynobj = abfd;
639
640 if (!htab->elf.splt
641 && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
642 /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
643 return false;
644
645 if (h->plt.refcount < 0)
646 h->plt.refcount = 0;
647 h->plt.refcount++;
648 h->needs_plt = 1;
649
650 elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
651 }
652
653 need_dynreloc = 0;
654 only_need_pcrel = 0;
655 switch (r_type)
656 {
657 case R_LARCH_SOP_PUSH_GPREL:
658 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
659 r_symndx,
660 GOT_NORMAL))
661 return false;
662 break;
663
664 case R_LARCH_SOP_PUSH_TLS_GD:
665 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
666 r_symndx,
667 GOT_TLS_GD))
668 return false;
669 break;
670
671 case R_LARCH_SOP_PUSH_TLS_GOT:
672 if (bfd_link_pic (info))
673 /* May fail for lazy-bind. */
674 info->flags |= DF_STATIC_TLS;
675
676 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
677 r_symndx,
678 GOT_TLS_IE))
679 return false;
680 break;
681
682 case R_LARCH_SOP_PUSH_TLS_TPREL:
683 if (!bfd_link_executable (info))
684 return false;
685
686 info->flags |= DF_STATIC_TLS;
687
688 if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
689 r_symndx,
690 GOT_TLS_LE))
691 return false;
692 break;
693
694 case R_LARCH_SOP_PUSH_ABSOLUTE:
695 if (h != NULL)
696 /* If this reloc is in a read-only section, we might
697 need a copy reloc. We can't check reliably at this
698 stage whether the section is read-only, as input
699 sections have not yet been mapped to output sections.
700 Tentatively set the flag for now, and correct in
701 adjust_dynamic_symbol. */
702 h->non_got_ref = 1;
703 break;
704
705 case R_LARCH_SOP_PUSH_PCREL:
706 if (h != NULL)
707 {
708 h->non_got_ref = 1;
709
710 /* We try to create PLT stub for all non-local function. */
711 if (h->plt.refcount < 0)
712 h->plt.refcount = 0;
713 h->plt.refcount++;
714 }
715 break;
716
717 case R_LARCH_SOP_PUSH_PLT_PCREL:
718 /* This symbol requires a procedure linkage table entry. We
719 actually build the entry in adjust_dynamic_symbol,
720 because this might be a case of linking PIC code without
721 linking in any dynamic objects, in which case we don't
722 need to generate a procedure linkage table after all. */
723 if (h != NULL)
724 {
725 h->needs_plt = 1;
726 if (h->plt.refcount < 0)
727 h->plt.refcount = 0;
728 h->plt.refcount++;
729 }
730 break;
731
732 case R_LARCH_TLS_DTPREL32:
733 case R_LARCH_TLS_DTPREL64:
734 need_dynreloc = 1;
735 only_need_pcrel = 1;
736 break;
737
738 case R_LARCH_JUMP_SLOT:
739 case R_LARCH_32:
740 case R_LARCH_64:
741 need_dynreloc = 1;
742
743 /* If resolved symbol is defined in this object,
744 1. Under pie, the symbol is known. We convert it
745 into R_LARCH_RELATIVE and need load-addr still.
746 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
747 3. Under dll, R_LARCH_NN can't be changed normally, since
748 its defination could be covered by the one in executable.
749 For symbolic, we convert it into R_LARCH_RELATIVE.
750 Thus, only under pde, it needs pcrel only. We discard it. */
751 only_need_pcrel = bfd_link_pde (info);
752
753 if (h != NULL)
754 h->non_got_ref = 1;
755 break;
756
757 case R_LARCH_GNU_VTINHERIT:
758 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
759 return false;
760 break;
761
762 case R_LARCH_GNU_VTENTRY:
763 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
764 return false;
765 break;
766
767 default:
768 break;
769 }
770
771 /* Record some info for sizing and allocating dynamic entry. */
772 if (need_dynreloc && (sec->flags & SEC_ALLOC))
773 {
774 /* When creating a shared object, we must copy these
775 relocs into the output file. We create a reloc
776 section in dynobj and make room for the reloc. */
777 struct elf_dyn_relocs *p;
778 struct elf_dyn_relocs **head;
779
780 if (sreloc == NULL)
781 {
782 sreloc
783 = _bfd_elf_make_dynamic_reloc_section (sec, htab->elf.dynobj,
784 LARCH_ELF_LOG_WORD_BYTES,
785 abfd, /*rela?*/ true);
786 if (sreloc == NULL)
787 return false;
788 }
789
790 /* If this is a global symbol, we count the number of
791 relocations we need for this symbol. */
792 if (h != NULL)
793 head = &((struct loongarch_elf_link_hash_entry *) h)->dyn_relocs;
794 else
795 {
796 /* Track dynamic relocs needed for local syms too.
797 We really need local syms available to do this
798 easily. Oh well. */
799
800 asection *s;
801 void *vpp;
802
803 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
804 if (s == NULL)
805 s = sec;
806
807 vpp = &elf_section_data (s)->local_dynrel;
808 head = (struct elf_dyn_relocs **) vpp;
809 }
810
811 p = *head;
812 if (p == NULL || p->sec != sec)
813 {
814 bfd_size_type amt = sizeof *p;
815 p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt);
816 if (p == NULL)
817 return false;
818 p->next = *head;
819 *head = p;
820 p->sec = sec;
821 p->count = 0;
822 p->pc_count = 0;
823 }
824
825 p->count++;
826 p->pc_count += only_need_pcrel;
827 }
828 }
829
830 return true;
831}
832
833/* Find dynamic relocs for H that apply to read-only sections. */
834
835static asection *
836readonly_dynrelocs (struct elf_link_hash_entry *h)
837{
838 struct elf_dyn_relocs *p;
839
840 for (p = loongarch_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
841 {
842 asection *s = p->sec->output_section;
843
844 if (s != NULL && (s->flags & SEC_READONLY) != 0)
845 return p->sec;
846 }
847 return NULL;
848}
849
850/* Adjust a symbol defined by a dynamic object and referenced by a
851 regular object. The current definition is in some section of the
852 dynamic object, but we're not including those sections. We have to
853 change the definition to something the rest of the link can
854 understand. */
855static bool
856loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
857 struct elf_link_hash_entry *h)
858{
859 struct loongarch_elf_link_hash_table *htab;
860 struct loongarch_elf_link_hash_entry *eh;
861 bfd *dynobj;
862 asection *s, *srel;
863
864 htab = loongarch_elf_hash_table (info);
865 BFD_ASSERT (htab != NULL);
866
867 dynobj = htab->elf.dynobj;
868
869 /* Make sure we know what is going on here. */
870 BFD_ASSERT (dynobj != NULL
871 && (h->needs_plt || h->type == STT_GNU_IFUNC || h->is_weakalias
872 || (h->def_dynamic && h->ref_regular && !h->def_regular)));
873
874 /* If this is a function, put it in the procedure linkage table. We
875 will fill in the contents of the procedure linkage table later
876 (although we could actually do it here). */
877 if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
878 {
879 if (h->plt.refcount < 0
880 || (h->type != STT_GNU_IFUNC
881 && (SYMBOL_REFERENCES_LOCAL (info, h)
882 || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
883 && h->root.type == bfd_link_hash_undefweak))))
884 {
885 /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
886 in an input file, but the symbol was never referred to by a
887 dynamic object, or if all references were garbage collected.
888 In such a case, we don't actually need to build a PLT entry. */
889 h->plt.offset = MINUS_ONE;
890 h->needs_plt = 0;
891 }
892 else
893 h->needs_plt = 1;
894
895 return true;
896 }
897 else
898 h->plt.offset = MINUS_ONE;
899
900 /* If this is a weak symbol, and there is a real definition, the
901 processor independent code will have arranged for us to see the
902 real definition first, and we can just use the same value. */
903 if (h->is_weakalias)
904 {
905 struct elf_link_hash_entry *def = weakdef (h);
906 BFD_ASSERT (def->root.type == bfd_link_hash_defined);
907 h->root.u.def.section = def->root.u.def.section;
908 h->root.u.def.value = def->root.u.def.value;
909 return true;
910 }
911
912 /* This is a reference to a symbol defined by a dynamic object which
913 is not a function. */
914
915 /* If we are creating a shared library, we must presume that the
916 only references to the symbol are via the global offset table.
917 For such cases we need not do anything here; the relocations will
918 be handled correctly by relocate_section. */
919 if (bfd_link_dll (info))
920 return true;
921
922 /* If there are no references to this symbol that do not use the
923 GOT, we don't need to generate a copy reloc. */
924 if (!h->non_got_ref)
925 return true;
926
927 /* If -z nocopyreloc was given, we won't generate them either. */
928 if (info->nocopyreloc)
929 {
930 h->non_got_ref = 0;
931 return true;
932 }
933
934 /* If we don't find any dynamic relocs in read-only sections, then
935 we'll be keeping the dynamic relocs and avoiding the copy reloc. */
936 if (!readonly_dynrelocs (h))
937 {
938 h->non_got_ref = 0;
939 return true;
940 }
941
942 /* We must allocate the symbol in our .dynbss section, which will
943 become part of the .bss section of the executable. There will be
944 an entry for this symbol in the .dynsym section. The dynamic
945 object will contain position independent code, so all references
946 from the dynamic object to this symbol will go through the global
947 offset table. The dynamic linker will use the .dynsym entry to
948 determine the address it must put in the global offset table, so
949 both the dynamic object and the regular object will refer to the
950 same memory location for the variable. */
951
952 /* We must generate a R_LARCH_COPY reloc to tell the dynamic linker
953 to copy the initial value out of the dynamic object and into the
954 runtime process image. We need to remember the offset into the
955 .rel.bss section we are going to use. */
956 eh = (struct loongarch_elf_link_hash_entry *) h;
957 if (eh->tls_type & ~GOT_NORMAL)
958 {
959 s = htab->sdyntdata;
960 srel = htab->elf.srelbss;
961 }
962 else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
963 {
964 s = htab->elf.sdynrelro;
965 srel = htab->elf.sreldynrelro;
966 }
967 else
968 {
969 s = htab->elf.sdynbss;
970 srel = htab->elf.srelbss;
971 }
972 if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
973 {
974 srel->size += sizeof (ElfNN_External_Rela);
975 h->needs_copy = 1;
976 }
977
978 return _bfd_elf_adjust_dynamic_copy (info, h, s);
979}
980
981/* Allocate space in .plt, .got and associated reloc sections for
982 dynamic relocs. */
983
984static bool
985allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
986{
987 struct bfd_link_info *info;
988 struct loongarch_elf_link_hash_table *htab;
989 struct loongarch_elf_link_hash_entry *eh;
990 struct elf_dyn_relocs *p;
991
992 if (h->root.type == bfd_link_hash_indirect)
993 return true;
994
995 eh = (struct loongarch_elf_link_hash_entry *) h;
996 info = (struct bfd_link_info *) inf;
997 htab = loongarch_elf_hash_table (info);
998 BFD_ASSERT (htab != NULL);
999
1000 do
1001 {
1002 asection *plt, *gotplt, *relplt;
1003
1004 if (!h->needs_plt)
1005 break;
1006
1007 h->needs_plt = 0;
1008
1009 if (htab->elf.splt)
1010 {
1011 if (h->dynindx == -1 && !h->forced_local
1012 && !bfd_elf_link_record_dynamic_symbol (info, h))
1013 return false;
1014
1015 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
1016 && h->type != STT_GNU_IFUNC)
1017 break;
1018
1019 plt = htab->elf.splt;
1020 gotplt = htab->elf.sgotplt;
1021 relplt = htab->elf.srelplt;
1022 }
1023 else if (htab->elf.iplt)
1024 {
1025 /* .iplt only for IFUNC. */
1026 if (h->type != STT_GNU_IFUNC)
1027 break;
1028
1029 plt = htab->elf.iplt;
1030 gotplt = htab->elf.igotplt;
1031 relplt = htab->elf.irelplt;
1032 }
1033 else
1034 break;
1035
1036 if (plt->size == 0)
1037 plt->size = PLT_HEADER_SIZE;
1038
1039 h->plt.offset = plt->size;
1040 plt->size += PLT_ENTRY_SIZE;
1041 gotplt->size += GOT_ENTRY_SIZE;
1042 relplt->size += sizeof (ElfNN_External_Rela);
1043
1044 h->needs_plt = 1;
1045 }
1046 while (0);
1047
1048 if (!h->needs_plt)
1049 h->plt.offset = MINUS_ONE;
1050
1051 if (0 < h->got.refcount)
1052 {
1053 asection *s;
1054 bool dyn;
1055 int tls_type = loongarch_elf_hash_entry (h)->tls_type;
1056
1057 /* Make sure this symbol is output as a dynamic symbol.
1058 Undefined weak syms won't yet be marked as dynamic. */
1059 if (h->dynindx == -1 && !h->forced_local
1060 && !bfd_elf_link_record_dynamic_symbol (info, h))
1061 return false;
1062
1063 s = htab->elf.sgot;
1064 h->got.offset = s->size;
1065 dyn = htab->elf.dynamic_sections_created;
1066 if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
1067 {
1068 /* TLS_GD needs two dynamic relocs and two GOT slots. */
1069 if (tls_type & GOT_TLS_GD)
1070 {
1071 s->size += 2 * GOT_ENTRY_SIZE;
1072 htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
1073 }
1074
1075 /* TLS_IE needs one dynamic reloc and one GOT slot. */
1076 if (tls_type & GOT_TLS_IE)
1077 {
1078 s->size += GOT_ENTRY_SIZE;
1079 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1080 }
1081 }
1082 else
1083 {
1084 s->size += GOT_ENTRY_SIZE;
1085 if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
1086 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
1087 || h->type == STT_GNU_IFUNC)
1088 htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
1089 }
1090 }
1091 else
1092 h->got.offset = MINUS_ONE;
1093
1094 if (eh->dyn_relocs == NULL)
1095 return true;
1096
1097 if (SYMBOL_REFERENCES_LOCAL (info, h))
1098 {
1099 struct elf_dyn_relocs **pp;
1100
1101 for (pp = &eh->dyn_relocs; (p = *pp) != NULL;)
1102 {
1103 p->count -= p->pc_count;
1104 p->pc_count = 0;
1105 if (p->count == 0)
1106 *pp = p->next;
1107 else
1108 pp = &p->next;
1109 }
1110 }
1111
1112 if (h->root.type == bfd_link_hash_undefweak)
1113 {
1114 if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
1115 eh->dyn_relocs = NULL;
1116 else if (h->dynindx == -1 && !h->forced_local
1117 /* Make sure this symbol is output as a dynamic symbol.
1118 Undefined weak syms won't yet be marked as dynamic. */
1119 && !bfd_elf_link_record_dynamic_symbol (info, h))
1120 return false;
1121 }
1122
1123 for (p = eh->dyn_relocs; p != NULL; p = p->next)
1124 {
1125 asection *sreloc = elf_section_data (p->sec)->sreloc;
1126 sreloc->size += p->count * sizeof (ElfNN_External_Rela);
1127 }
1128
1129 return true;
1130}
1131
1132static bool
1133elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf)
1134{
1135 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
1136
1137 if (!h->def_regular || !h->ref_regular || !h->forced_local
1138 || h->root.type != bfd_link_hash_defined)
1139 abort ();
1140
1141 return allocate_dynrelocs (h, inf);
1142}
1143
1144/* Set DF_TEXTREL if we find any dynamic relocs that apply to
1145 read-only sections. */
1146
1147static bool
1148maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
1149{
1150 asection *sec;
1151
1152 if (h->root.type == bfd_link_hash_indirect)
1153 return true;
1154
1155 sec = readonly_dynrelocs (h);
1156 if (sec != NULL)
1157 {
1158 struct bfd_link_info *info = (struct bfd_link_info *) info_p;
1159
1160 info->flags |= DF_TEXTREL;
1161 info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' in "
1162 "read-only section `%pA'\n"),
1163 sec->owner, h->root.root.string, sec);
1164
1165 /* Not an error, just cut short the traversal. */
1166 return false;
1167 }
1168 return true;
1169}
1170
1171static bool
1172loongarch_elf_size_dynamic_sections (bfd *output_bfd,
1173 struct bfd_link_info *info)
1174{
1175 struct loongarch_elf_link_hash_table *htab;
1176 bfd *dynobj;
1177 asection *s;
1178 bfd *ibfd;
1179
1180 htab = loongarch_elf_hash_table (info);
1181 BFD_ASSERT (htab != NULL);
1182 dynobj = htab->elf.dynobj;
1183 BFD_ASSERT (dynobj != NULL);
1184
1185 if (htab->elf.dynamic_sections_created)
1186 {
1187 /* Set the contents of the .interp section to the interpreter. */
1188 if (bfd_link_executable (info) && !info->nointerp)
1189 {
1190 const char *interpreter;
1191 flagword flags = elf_elfheader (output_bfd)->e_flags;
1192 s = bfd_get_linker_section (dynobj, ".interp");
1193 BFD_ASSERT (s != NULL);
1194 if (EF_LOONGARCH_IS_ILP32 (flags))
1195 interpreter = "/lib32/ld.so.1";
1196 else if (EF_LOONGARCH_IS_LP64 (flags))
1197 interpreter = "/lib64/ld.so.1";
1198 else
1199 interpreter = "/lib/ld.so.1";
1200 s->contents = (unsigned char *) interpreter;
1201 s->size = strlen (interpreter) + 1;
1202 }
1203 }
1204
1205 /* Set up .got offsets for local syms, and space for local dynamic
1206 relocs. */
1207 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
1208 {
1209 bfd_signed_vma *local_got;
1210 bfd_signed_vma *end_local_got;
1211 char *local_tls_type;
1212 bfd_size_type locsymcount;
1213 Elf_Internal_Shdr *symtab_hdr;
1214 asection *srel;
1215
1216 if (!is_loongarch_elf (ibfd))
1217 continue;
1218
1219 for (s = ibfd->sections; s != NULL; s = s->next)
1220 {
1221 struct elf_dyn_relocs *p;
1222
1223 for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
1224 {
1225 p->count -= p->pc_count;
1226 if (!bfd_is_abs_section (p->sec)
1227 && bfd_is_abs_section (p->sec->output_section))
1228 {
1229 /* Input section has been discarded, either because
1230 it is a copy of a linkonce section or due to
1231 linker script /DISCARD/, so we'll be discarding
1232 the relocs too. */
1233 }
1234 else if (0 < p->count)
1235 {
1236 srel = elf_section_data (p->sec)->sreloc;
1237 srel->size += p->count * sizeof (ElfNN_External_Rela);
1238 if ((p->sec->output_section->flags & SEC_READONLY) != 0)
1239 info->flags |= DF_TEXTREL;
1240 }
1241 }
1242 }
1243
1244 local_got = elf_local_got_refcounts (ibfd);
1245 if (!local_got)
1246 continue;
1247
1248 symtab_hdr = &elf_symtab_hdr (ibfd);
1249 locsymcount = symtab_hdr->sh_info;
1250 end_local_got = local_got + locsymcount;
1251 local_tls_type = _bfd_loongarch_elf_local_got_tls_type (ibfd);
1252 s = htab->elf.sgot;
1253 srel = htab->elf.srelgot;
1254 for (; local_got < end_local_got; ++local_got, ++local_tls_type)
1255 {
1256 if (0 < *local_got)
1257 {
1258 *local_got = s->size;
1259 s->size += GOT_ENTRY_SIZE;
1260
1261 if (*local_tls_type & GOT_TLS_GD)
1262 s->size += GOT_ENTRY_SIZE;
1263
1264 /* If R_LARCH_RELATIVE. */
1265 if (bfd_link_pic (info)
1266 /* Or R_LARCH_TLS_DTPRELNN or R_LARCH_TLS_TPRELNN. */
1267 || (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE)))
1268 srel->size += sizeof (ElfNN_External_Rela);
1269 }
1270 else
1271 *local_got = MINUS_ONE;
1272 }
1273 }
1274
1275 /* Allocate global sym .plt and .got entries, and space for global
1276 sym dynamic relocs. */
1277 elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
1278 /* Allocate .plt and .got entries, and space for local ifunc symbols. */
1279 htab_traverse (htab->loc_hash_table,
1280 (void *) elfNN_loongarch_allocate_local_dynrelocs, info);
1281
1282 /* Don't allocate .got.plt section if there are no PLT. */
1283 if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE
1284 && (htab->elf.splt == NULL || htab->elf.splt->size == 0))
1285 htab->elf.sgotplt->size = 0;
1286
1287 /* The check_relocs and adjust_dynamic_symbol entry points have
1288 determined the sizes of the various dynamic sections. Allocate
1289 memory for them. */
1290 for (s = dynobj->sections; s != NULL; s = s->next)
1291 {
1292 if ((s->flags & SEC_LINKER_CREATED) == 0)
1293 continue;
1294
1295 if (s == htab->elf.splt || s == htab->elf.iplt || s == htab->elf.sgot
1296 || s == htab->elf.sgotplt || s == htab->elf.igotplt
1297 || s == htab->elf.sdynbss || s == htab->elf.sdynrelro)
1298 {
1299 /* Strip this section if we don't need it; see the
1300 comment below. */
1301 }
1302 else if (strncmp (s->name, ".rela", 5) == 0)
1303 {
1304 if (s->size != 0)
1305 {
1306 /* We use the reloc_count field as a counter if we need
1307 to copy relocs into the output file. */
1308 s->reloc_count = 0;
1309 }
1310 }
1311 else
1312 {
1313 /* It's not one of our sections. */
1314 continue;
1315 }
1316
1317 if (s->size == 0)
1318 {
1319 /* If we don't need this section, strip it from the
1320 output file. This is mostly to handle .rela.bss and
1321 .rela.plt. We must create both sections in
1322 create_dynamic_sections, because they must be created
1323 before the linker maps input sections to output
1324 sections. The linker does that before
1325 adjust_dynamic_symbol is called, and it is that
1326 function which decides whether anything needs to go
1327 into these sections. */
1328 s->flags |= SEC_EXCLUDE;
1329 continue;
1330 }
1331
1332 if ((s->flags & SEC_HAS_CONTENTS) == 0)
1333 continue;
1334
1335 /* Allocate memory for the section contents. Zero the memory
1336 for the benefit of .rela.plt, which has 4 unused entries
1337 at the beginning, and we don't want garbage. */
1338 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
1339 if (s->contents == NULL)
1340 return false;
1341 }
1342
1343 if (elf_hash_table (info)->dynamic_sections_created)
1344 {
1345 /* Add some entries to the .dynamic section. We fill in the
1346 values later, in loongarch_elf_finish_dynamic_sections, but we
1347 must add the entries now so that we get the correct size for
1348 the .dynamic section. The DT_DEBUG entry is filled in by the
1349 dynamic linker and used by the debugger. */
1350#define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
1351
1352 if (bfd_link_executable (info))
1353 {
1354 if (!add_dynamic_entry (DT_DEBUG, 0))
1355 return false;
1356 }
1357
1358 if (htab->elf.srelplt->size != 0)
1359 {
1360 if (!add_dynamic_entry (DT_PLTGOT, 0)
1361 || !add_dynamic_entry (DT_PLTRELSZ, 0)
1362 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
1363 || !add_dynamic_entry (DT_JMPREL, 0))
1364 return false;
1365 }
1366
1367 if (!add_dynamic_entry (DT_RELA, 0)
1368 || !add_dynamic_entry (DT_RELASZ, 0)
1369 || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
1370 return false;
1371
1372 /* If any dynamic relocs apply to a read-only section,
1373 then we need a DT_TEXTREL entry. */
1374 if ((info->flags & DF_TEXTREL) == 0)
1375 elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
1376
1377 if (info->flags & DF_TEXTREL)
1378 {
1379 if (!add_dynamic_entry (DT_TEXTREL, 0))
1380 return false;
1381 /* Clear the DF_TEXTREL flag. It will be set again if we
1382 write out an actual text relocation; we may not, because
1383 at this point we do not know whether e.g. any .eh_frame
1384 absolute relocations have been converted to PC-relative. */
1385 info->flags &= ~DF_TEXTREL;
1386 }
1387 }
1388#undef add_dynamic_entry
1389
1390 return true;
1391}
1392
1393#define LARCH_LD_STACK_DEPTH 16
1394static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
1395static size_t larch_stack_top = 0;
1396
1397static bfd_reloc_status_type
1398loongarch_push (int64_t val)
1399{
1400 if (LARCH_LD_STACK_DEPTH <= larch_stack_top)
1401 return bfd_reloc_outofrange;
1402 larch_opc_stack[larch_stack_top++] = val;
1403 return bfd_reloc_ok;
1404}
1405
1406static bfd_reloc_status_type
1407loongarch_pop (int64_t *val)
1408{
1409 if (larch_stack_top == 0)
1410 return bfd_reloc_outofrange;
1411 BFD_ASSERT (val);
1412 *val = larch_opc_stack[--larch_stack_top];
1413 return bfd_reloc_ok;
1414}
1415
1416static bfd_reloc_status_type
1417loongarch_top (int64_t *val)
1418{
1419 if (larch_stack_top == 0)
1420 return bfd_reloc_outofrange;
1421 BFD_ASSERT (val);
1422 *val = larch_opc_stack[larch_stack_top - 1];
1423 return bfd_reloc_ok;
1424}
1425
1426static void
1427loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
1428{
1429 const struct elf_backend_data *bed;
1430 bfd_byte *loc;
1431
1432 bed = get_elf_backend_data (abfd);
1433 loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
1434 bed->s->swap_reloca_out (abfd, rel, loc);
1435}
1436
1437/* Check rel->r_offset in range of contents. */
1438static bfd_reloc_status_type
1439loongarch_check_offset (const Elf_Internal_Rela *rel,
1440 const asection *input_section)
1441{
1442 if (0 == strcmp(input_section->name, ".text")
1443 && rel->r_offset > input_section->size)
1444 return bfd_reloc_overflow;
1445
1446 return bfd_reloc_ok;
1447}
1448
e214f8db 1449#define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1450 ({ \
1451 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1452 if (ret == bfd_reloc_ok) \
1453 { \
1454 ret = loongarch_pop (&op1); \
1455 if (ret == bfd_reloc_ok) \
1456 ret = loongarch_push (op3); \
1457 } \
1458 ret; \
1459 })
1460
e214f8db 1461static bfd_reloc_status_type
1462loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
1463 const asection *input_section ATTRIBUTE_UNUSED,
1464 reloc_howto_type *howto, bfd *input_bfd,
748594bc 1465 bfd_byte *contents, bfd_vma reloc_val)
e214f8db 1466{
e214f8db 1467 int bits = bfd_get_reloc_size (howto) * 8;
1468 uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
1469
748594bc 1470 if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
1471 return bfd_reloc_overflow;
1472
1473 insn = (insn & (uint32_t)howto->src_mask)
1474 | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val);
1475
e214f8db 1476 bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
1477
1478 return bfd_reloc_ok;
1479}
1480
1481/* Emplace a static relocation. */
1482
1483static bfd_reloc_status_type
1484perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
1485 reloc_howto_type *howto, bfd_vma value,
1486 bfd *input_bfd, bfd_byte *contents)
1487{
1488 uint32_t insn1;
1489 int64_t opr1, opr2, opr3;
1490 bfd_reloc_status_type r = bfd_reloc_ok;
1491 int bits = bfd_get_reloc_size (howto) * 8;
1492
1493
1494 switch (ELFNN_R_TYPE (rel->r_info))
1495 {
1496 case R_LARCH_SOP_PUSH_PCREL:
1497 case R_LARCH_SOP_PUSH_ABSOLUTE:
1498 case R_LARCH_SOP_PUSH_GPREL:
1499 case R_LARCH_SOP_PUSH_TLS_TPREL:
1500 case R_LARCH_SOP_PUSH_TLS_GOT:
1501 case R_LARCH_SOP_PUSH_TLS_GD:
1502 case R_LARCH_SOP_PUSH_PLT_PCREL:
1503 r = loongarch_push (value);
1504 break;
1505
1506 case R_LARCH_SOP_PUSH_DUP:
1507 r = loongarch_pop (&opr1);
1508 if (r == bfd_reloc_ok)
1509 {
1510 r = loongarch_push (opr1);
1511 if (r == bfd_reloc_ok)
1512 r = loongarch_push (opr1);
1513 }
1514 break;
1515
1516 case R_LARCH_SOP_ASSERT:
1517 r = loongarch_pop (&opr1);
1518 if (r != bfd_reloc_ok || !opr1)
1519 r = bfd_reloc_notsupported;
1520 break;
1521
1522 case R_LARCH_SOP_NOT:
1523 r = loongarch_pop (&opr1);
1524 if (r == bfd_reloc_ok)
1525 r = loongarch_push (!opr1);
1526 break;
1527
1528 case R_LARCH_SOP_SUB:
1529 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
1530 break;
1531
1532 case R_LARCH_SOP_SL:
1533 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
1534 break;
1535
1536 case R_LARCH_SOP_SR:
1537 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
1538 break;
1539
1540 case R_LARCH_SOP_AND:
1541 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
1542 break;
1543
1544 case R_LARCH_SOP_ADD:
1545 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
1546 break;
1547
1548 case R_LARCH_SOP_IF_ELSE:
1549 r = loongarch_pop (&opr3);
1550 if (r == bfd_reloc_ok)
1551 {
1552 r = loongarch_pop (&opr2);
1553 if (r == bfd_reloc_ok)
1554 {
1555 r = loongarch_pop (&opr1);
1556 if (r == bfd_reloc_ok)
1557 r = loongarch_push (opr1 ? opr2 : opr3);
1558 }
1559 }
1560 break;
1561
1562 case R_LARCH_SOP_POP_32_S_10_5:
1563 case R_LARCH_SOP_POP_32_S_10_12:
1564 case R_LARCH_SOP_POP_32_S_10_16:
1565 case R_LARCH_SOP_POP_32_S_10_16_S2:
1566 case R_LARCH_SOP_POP_32_S_5_20:
e214f8db 1567 case R_LARCH_SOP_POP_32_U_10_12:
748594bc 1568 case R_LARCH_SOP_POP_32_U:
e214f8db 1569 r = loongarch_pop (&opr1);
1570 if (r != bfd_reloc_ok)
1571 break;
1572 r = loongarch_check_offset (rel, input_section);
1573 if (r != bfd_reloc_ok)
1574 break;
1575
1576 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
1577 howto, input_bfd,
748594bc 1578 contents, (bfd_vma)opr1);
e214f8db 1579 break;
1580
1581 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
748594bc 1582 {
1583 r = loongarch_pop (&opr1);
1584 if (r != bfd_reloc_ok)
e214f8db 1585 break;
e214f8db 1586
748594bc 1587 if ((opr1 & 0x3) != 0)
1588 {
1589 r = bfd_reloc_overflow;
1590 break;
1591 }
1592
1593 uint32_t imm = opr1 >> howto->rightshift;
1594 if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU)))
1595 {
1596 r = bfd_reloc_overflow;
1597 break;
1598 }
1599 r = loongarch_check_offset (rel, input_section);
1600 if (r != bfd_reloc_ok)
e214f8db 1601 break;
e214f8db 1602
748594bc 1603 insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1604 insn1 = (insn1 & howto->src_mask)
1605 | ((imm & 0xffffU) << 10)
1606 | ((imm & 0x1f0000U) >> 16);
1607 bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
e214f8db 1608 break;
748594bc 1609 }
e214f8db 1610
1611 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1612 {
1613 r = loongarch_pop (&opr1);
1614 if (r != bfd_reloc_ok)
1615 break;
1616
1617 if ((opr1 & 0x3) != 0)
1618 {
1619 r = bfd_reloc_overflow;
1620 break;
1621 }
1622
1623 uint32_t imm = opr1 >> howto->rightshift;
1624 if ((imm & (~0x1ffffffU)) && (imm & (~0x1ffffffU)) != (~0x1ffffffU))
1625 {
1626 r = bfd_reloc_overflow;
1627 break;
1628 }
1629
1630 r = loongarch_check_offset (rel, input_section);
1631 if (r != bfd_reloc_ok)
1632 break;
1633
1634 insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1635 insn1 = ((insn1 & howto->src_mask)
1636 | ((imm & 0xffffU) << 10)
1637 | ((imm & 0x3ff0000U) >> 16));
1638 bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
1639 break;
1640 }
1641
e214f8db 1642 case R_LARCH_TLS_DTPREL32:
1643 case R_LARCH_32:
1644 case R_LARCH_TLS_DTPREL64:
1645 case R_LARCH_64:
1646 r = loongarch_check_offset (rel, input_section);
1647 if (r != bfd_reloc_ok)
1648 break;
1649
1650 bfd_put (bits, input_bfd, value, contents + rel->r_offset);
1651 break;
1652
1653 case R_LARCH_ADD8:
1654 case R_LARCH_ADD16:
1655 case R_LARCH_ADD24:
1656 case R_LARCH_ADD32:
1657 case R_LARCH_ADD64:
1658 r = loongarch_check_offset (rel, input_section);
1659 if (r != bfd_reloc_ok)
1660 break;
1661
1662 opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1663 bfd_put (bits, input_bfd, opr1 + value, contents + rel->r_offset);
1664 break;
1665
1666 case R_LARCH_SUB8:
1667 case R_LARCH_SUB16:
1668 case R_LARCH_SUB24:
1669 case R_LARCH_SUB32:
1670 case R_LARCH_SUB64:
1671 r = loongarch_check_offset (rel, input_section);
1672 if (r != bfd_reloc_ok)
1673 break;
1674
1675 opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1676 bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
1677 break;
1678
1679 default:
1680 r = bfd_reloc_notsupported;
1681 }
1682 return r;
1683}
1684
1685#define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
1686static struct
1687{
1688 bfd *bfd;
1689 asection *section;
1690 bfd_vma r_offset;
1691 int r_type;
1692 bfd_vma relocation;
1693 Elf_Internal_Sym *sym;
1694 struct elf_link_hash_entry *h;
1695 bfd_vma addend;
1696 int64_t top_then;
1697} larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
1698static size_t larch_reloc_queue_head = 0;
1699static size_t larch_reloc_queue_tail = 0;
1700
1701static const char *
1702loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
1703 Elf_Internal_Sym *sym)
1704{
1705 const char *ret = NULL;
1706 if (sym)
1707 ret = bfd_elf_string_from_elf_section (input_bfd,
1708 elf_symtab_hdr (input_bfd).sh_link,
1709 sym->st_name);
1710 else if (h)
1711 ret = h->root.root.string;
1712
1713 if (ret == NULL || *ret == '\0')
1714 ret = "<nameless>";
1715 return ret;
1716}
1717
1718static void
1719loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
1720 bfd_vma r_offset, Elf_Internal_Sym *sym,
1721 struct elf_link_hash_entry *h, bfd_vma addend)
1722{
1723 if ((larch_reloc_queue_head == 0
1724 && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
1725 || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
1726 larch_reloc_queue_head =
1727 (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
1728 larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
1729 larch_reloc_queue[larch_reloc_queue_tail].section = section;
1730 larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
1731 larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
1732 larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
1733 larch_reloc_queue[larch_reloc_queue_tail].h = h;
1734 larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
1735 loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
1736 larch_reloc_queue_tail =
1737 (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
1738}
1739
1740static void
1741loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
1742{
1743 size_t i = larch_reloc_queue_head;
1744 bfd *a_bfd = NULL;
1745 asection *section = NULL;
1746 bfd_vma r_offset = 0;
1747 int inited = 0;
1748 p ("Dump relocate record:\n");
1749 p ("stack top\t\trelocation name\t\tsymbol");
1750 while (i != larch_reloc_queue_tail)
1751 {
1752 if (a_bfd != larch_reloc_queue[i].bfd
1753 || section != larch_reloc_queue[i].section
1754 || r_offset != larch_reloc_queue[i].r_offset)
1755 {
1756 a_bfd = larch_reloc_queue[i].bfd;
1757 section = larch_reloc_queue[i].section;
1758 r_offset = larch_reloc_queue[i].r_offset;
1759 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
1760 larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
1761 }
1762
1763 if (!inited)
1764 inited = 1, p ("...\n");
1765
1766 reloc_howto_type *howto =
1767 loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
1768 larch_reloc_queue[i].r_type);
1769 p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
1770 howto ? howto->name : "<unknown reloc>",
1771 loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
1772 larch_reloc_queue[i].sym));
1773
1774 long addend = larch_reloc_queue[i].addend;
1775 if (addend < 0)
1776 p (" - %ld", -addend);
1777 else if (0 < addend)
1778 p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
1779
1780 p ("\n");
1781 i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
1782 }
1783 p ("\n"
1784 "-- Record dump end --\n\n");
1785}
1786
1787
1788static bool
1789loongarch_reloc_is_fatal (struct bfd_link_info *info,
1790 bfd *input_bfd,
1791 asection *input_section,
1792 Elf_Internal_Rela *rel,
1793 reloc_howto_type *howto,
1794 bfd_reloc_status_type rtype,
1795 bool is_undefweak,
1796 const char *name,
1797 const char *msg)
1798{
1799 bool fatal = true;
1800 switch (rtype)
1801 {
1802 /* 'dangerous' means we do it but can't promise it's ok
1803 'unsupport' means out of ability of relocation type
1804 'undefined' means we can't deal with the undefined symbol. */
1805 case bfd_reloc_undefined:
1806 info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
1807 rel->r_offset, true);
1808 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1809 input_bfd, input_section, rel->r_offset,
1810 howto->name,
1811 is_undefweak ? "[undefweak] " : "", name, msg);
1812 break;
1813 case bfd_reloc_dangerous:
1814 info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
1815 input_bfd, input_section, rel->r_offset,
1816 howto->name,
1817 is_undefweak ? "[undefweak] " : "", name, msg);
1818 fatal = false;
1819 break;
1820 case bfd_reloc_notsupported:
1821 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1822 input_bfd, input_section, rel->r_offset,
1823 howto->name,
1824 is_undefweak ? "[undefweak] " : "", name, msg);
1825 break;
1826 default:
1827 break;
1828 }
1829 return fatal;
1830}
1831
1832
1833
1834
1835static int
1836loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
1837 bfd *input_bfd, asection *input_section,
1838 bfd_byte *contents, Elf_Internal_Rela *relocs,
1839 Elf_Internal_Sym *local_syms,
1840 asection **local_sections)
1841{
1842 Elf_Internal_Rela *rel;
1843 Elf_Internal_Rela *relend;
1844 bool fatal = false;
1845 asection *sreloc = elf_section_data (input_section)->sreloc;
1846 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
1847 Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
1848 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
1849 bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
1850 bool is_pic = bfd_link_pic (info);
1851 bool is_dyn = elf_hash_table (info)->dynamic_sections_created;
1852 asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
1853 asection *got = htab->elf.sgot;
1854
1855 relend = relocs + input_section->reloc_count;
1856 for (rel = relocs; rel < relend; rel++)
1857 {
1858 int r_type = ELFNN_R_TYPE (rel->r_info);
1859 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
1860 bfd_vma pc = sec_addr (input_section) + rel->r_offset;
1861 reloc_howto_type *howto = NULL;
1862 asection *sec = NULL;
1863 Elf_Internal_Sym *sym = NULL;
1864 struct elf_link_hash_entry *h = NULL;
1865 const char *name;
1866 bfd_reloc_status_type r = bfd_reloc_ok;
1867 bool is_ie, is_undefweak, unresolved_reloc, defined_local;
1868 bool resolved_local, resolved_dynly, resolved_to_const;
1869 char tls_type;
1870 bfd_vma relocation;
1871 bfd_vma off, ie_off;
1872 int i, j;
1873
1874 howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
1875 if (howto == NULL || r_type == R_LARCH_GNU_VTINHERIT
1876 || r_type == R_LARCH_GNU_VTENTRY)
1877 continue;
1878
1879 /* This is a final link. */
1880 if (r_symndx < symtab_hdr->sh_info)
1881 {
1882 is_undefweak = false;
1883 unresolved_reloc = false;
1884 sym = local_syms + r_symndx;
1885 sec = local_sections[r_symndx];
1886 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1887
1888 /* Relocate against local STT_GNU_IFUNC symbol. */
1889 if (!bfd_link_relocatable (info)
1890 && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
1891 {
1892 h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
1893 false);
1894 if (h == NULL)
1895 abort ();
1896
1897 /* Set STT_GNU_IFUNC symbol value. */
1898 h->root.u.def.value = sym->st_value;
1899 h->root.u.def.section = sec;
1900 }
1901 defined_local = true;
1902 resolved_local = true;
1903 resolved_dynly = false;
1904 resolved_to_const = false;
1905 if (bfd_link_relocatable (info)
1906 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1907 rel->r_addend += sec->output_offset;
1908 }
1909 else
1910 {
1911 bool warned, ignored;
1912
1913 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1914 r_symndx, symtab_hdr, sym_hashes,
1915 h, sec, relocation,
1916 unresolved_reloc, warned, ignored);
1917 /* Here means symbol isn't local symbol only and 'h != NULL'. */
1918
1919 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
1920 symbol. And 'dynamic_undefined_weak' specify what to do when
1921 meeting undefweak. */
1922
1923 if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
1924 {
1925 defined_local = false;
1926 resolved_local = false;
1927 resolved_to_const = (!is_dyn || h->dynindx == -1
1928 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
1929 resolved_dynly = !resolved_local && !resolved_to_const;
1930 }
1931 else if (warned)
1932 {
1933 /* Symbol undefined offen means failed already. I don't know why
1934 'warned' here but I guess it want to continue relocating as if
1935 no error occures to find other errors as more as possible. */
1936
1937 /* To avoid generating warning messages about truncated
1938 relocations, set the relocation's address to be the same as
1939 the start of this section. */
1940 relocation = (input_section->output_section
1941 ? input_section->output_section->vma
1942 : 0);
1943
1944 defined_local = relocation != 0;
1945 resolved_local = defined_local;
1946 resolved_to_const = !resolved_local;
1947 resolved_dynly = false;
1948 }
1949 else
1950 {
1951 defined_local = !unresolved_reloc && !ignored;
1952 resolved_local =
1953 defined_local && SYMBOL_REFERENCES_LOCAL (info, h);
1954 resolved_dynly = !resolved_local;
1955 resolved_to_const = !resolved_local && !resolved_dynly;
1956 }
1957 }
1958
1959 name = loongarch_sym_name (input_bfd, h, sym);
1960
1961 if (sec != NULL && discarded_section (sec))
1962 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
1963 1, relend, howto, 0, contents);
1964
1965 if (bfd_link_relocatable (info))
1966 continue;
1967
1968 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1969 from removed linkonce sections, or sections discarded by a linker
1970 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
1971 if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
1972 {
1973 defined_local = false;
1974 resolved_local = false;
1975 resolved_dynly = false;
1976 resolved_to_const = true;
1977 }
1978
1979 if (h && h->type == STT_GNU_IFUNC)
1980 {
1981 if (h->plt.offset == MINUS_ONE)
1982 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against `%s':\n"
1983 "STT_GNU_IFUNC must have PLT stub"
1984 "\n",
1985 input_bfd, input_section,
1986 (bfd_vma) rel->r_offset, howto->name, name);
1987 defined_local = true;
1988 resolved_local = true;
1989 resolved_dynly = false;
1990 resolved_to_const = false;
1991 relocation = sec_addr (plt) + h->plt.offset;
1992 }
1993
1994 unresolved_reloc = resolved_dynly;
1995
1996 BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
1997
1998 BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));
1999
2000 BFD_ASSERT (!resolved_local || defined_local);
2001
2002 is_ie = false;
2003 switch (r_type)
2004 {
2005 case R_LARCH_MARK_PCREL:
2006 case R_LARCH_MARK_LA:
2007 case R_LARCH_NONE:
2008 r = bfd_reloc_continue;
2009 unresolved_reloc = false;
2010 break;
2011
2012 case R_LARCH_32:
2013 case R_LARCH_64:
2014 if (resolved_dynly || (is_pic && resolved_local))
2015 {
2016 Elf_Internal_Rela outrel;
2017
2018 /* When generating a shared object, these relocations are copied
2019 into the output file to be resolved at run time. */
2020
2021 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2022 input_section,
2023 rel->r_offset);
2024
2025 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2026 && (input_section->flags & SEC_ALLOC));
2027
2028 outrel.r_offset += sec_addr (input_section);
2029 if (resolved_dynly)
2030 {
2031 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2032 outrel.r_addend = rel->r_addend;
2033 }
2034 else
2035 {
2036 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2037 outrel.r_addend = relocation + rel->r_addend;
2038 }
2039
2040 if (unresolved_reloc)
2041 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2042 }
2043
2044 relocation += rel->r_addend;
2045 break;
2046
2047 case R_LARCH_ADD8:
2048 case R_LARCH_ADD16:
2049 case R_LARCH_ADD24:
2050 case R_LARCH_ADD32:
2051 case R_LARCH_ADD64:
2052 case R_LARCH_SUB8:
2053 case R_LARCH_SUB16:
2054 case R_LARCH_SUB24:
2055 case R_LARCH_SUB32:
2056 case R_LARCH_SUB64:
2057 if (resolved_dynly)
2058 fatal = (loongarch_reloc_is_fatal
2059 (info, input_bfd, input_section, rel, howto,
2060 bfd_reloc_undefined, is_undefweak, name,
2061 "Can't be resolved dynamically. "
2062 "If this procedure is hand-written assembly,\n"
2063 "there must be something like '.dword sym1 - sym2' "
2064 "to generate these relocs\n"
2065 "and we can't get known link-time address of "
2066 "these symbols."));
2067 else
2068 relocation += rel->r_addend;
2069 break;
2070
2071 case R_LARCH_TLS_DTPREL32:
2072 case R_LARCH_TLS_DTPREL64:
2073 if (resolved_dynly)
2074 {
2075 Elf_Internal_Rela outrel;
2076
2077 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2078 input_section,
2079 rel->r_offset);
2080 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2081 && (input_section->flags & SEC_ALLOC));
2082 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2083 outrel.r_offset += sec_addr (input_section);
2084 outrel.r_addend = rel->r_addend;
2085 if (unresolved_reloc)
2086 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2087 break;
2088 }
2089
2090 if (resolved_to_const)
2091 fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
2092 rel, howto,
2093 bfd_reloc_notsupported,
2094 is_undefweak, name,
2095 "Internal:");
2096 break;
2097
2098 case R_LARCH_SOP_PUSH_TLS_TPREL:
2099 if (resolved_local)
2100 {
2101 if (!elf_hash_table (info)->tls_sec)
2102 fatal = (loongarch_reloc_is_fatal
2103 (info, input_bfd, input_section, rel, howto,
2104 bfd_reloc_notsupported, is_undefweak, name,
2105 "TLS section not be created"));
2106 else
2107 relocation -= elf_hash_table (info)->tls_sec->vma;
2108 }
2109 else
2110 fatal = (loongarch_reloc_is_fatal
2111 (info, input_bfd, input_section, rel, howto,
2112 bfd_reloc_undefined, is_undefweak, name,
2113 "TLS LE just can be resolved local only."));
2114 break;
2115
2116 case R_LARCH_SOP_PUSH_ABSOLUTE:
2117 if (is_undefweak)
2118 {
2119 if (resolved_dynly)
2120 fatal = (loongarch_reloc_is_fatal
2121 (info, input_bfd, input_section, rel, howto,
2122 bfd_reloc_dangerous, is_undefweak, name,
2123 "Someone require us to resolve undefweak "
2124 "symbol dynamically. \n"
2125 "But this reloc can't be done. "
2126 "I think I can't throw error "
2127 "for this\n"
2128 "so I resolved it to 0. "
2129 "I suggest to re-compile with '-fpic'."));
2130
2131 relocation = 0;
2132 unresolved_reloc = false;
2133 break;
2134 }
2135
2136 if (resolved_to_const)
2137 {
2138 relocation += rel->r_addend;
2139 break;
2140 }
2141
2142 if (is_pic)
2143 {
2144 fatal = (loongarch_reloc_is_fatal
2145 (info, input_bfd, input_section, rel, howto,
2146 bfd_reloc_notsupported, is_undefweak, name,
2147 "Under PIC we don't know load address. Re-compile "
2148 "with '-fpic'?"));
2149 break;
2150 }
2151
2152 if (resolved_dynly)
2153 {
2154 if (!(plt && h && h->plt.offset != MINUS_ONE))
2155 {
2156 fatal = (loongarch_reloc_is_fatal
2157 (info, input_bfd, input_section, rel, howto,
2158 bfd_reloc_undefined, is_undefweak, name,
2159 "Can't be resolved dynamically. Try to re-compile "
2160 "with '-fpic'?"));
2161 break;
2162 }
2163
2164 if (rel->r_addend != 0)
2165 {
2166 fatal = (loongarch_reloc_is_fatal
2167 (info, input_bfd, input_section, rel, howto,
2168 bfd_reloc_notsupported, is_undefweak, name,
2169 "Shouldn't be with r_addend."));
2170 break;
2171 }
2172
2173 relocation = sec_addr (plt) + h->plt.offset;
2174 unresolved_reloc = false;
2175 break;
2176 }
2177
2178 if (resolved_local)
2179 {
2180 relocation += rel->r_addend;
2181 break;
2182 }
2183
2184 break;
2185
2186 case R_LARCH_SOP_PUSH_PCREL:
2187 case R_LARCH_SOP_PUSH_PLT_PCREL:
2188 unresolved_reloc = false;
2189
2190 if (resolved_to_const)
2191 {
2192 relocation += rel->r_addend;
2193 break;
2194 }
2195 else if (is_undefweak)
2196 {
2197 i = 0, j = 0;
2198 relocation = 0;
2199 if (resolved_dynly)
2200 {
2201 if (h && h->plt.offset != MINUS_ONE)
2202 i = 1, j = 2;
2203 else
2204 fatal = (loongarch_reloc_is_fatal
2205 (info, input_bfd, input_section, rel, howto,
2206 bfd_reloc_dangerous, is_undefweak, name,
2207 "Undefweak need to be resolved dynamically, "
2208 "but PLT stub doesn't represent."));
2209 }
2210 }
2211 else
2212 {
2213 if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
2214 {
2215 fatal = (loongarch_reloc_is_fatal
2216 (info, input_bfd, input_section, rel, howto,
2217 bfd_reloc_undefined, is_undefweak, name,
2218 "PLT stub does not represent and "
2219 "symbol not defined."));
2220 break;
2221 }
2222
2223 if (resolved_local)
2224 i = 0, j = 2;
2225 else /* if (resolved_dynly) */
2226 {
2227 if (!(h && h->plt.offset != MINUS_ONE))
2228 fatal = (loongarch_reloc_is_fatal
2229 (info, input_bfd, input_section, rel, howto,
2230 bfd_reloc_dangerous, is_undefweak, name,
2231 "Internal: PLT stub doesn't represent. "
2232 "Resolve it with pcrel"));
2233 i = 1, j = 3;
2234 }
2235 }
2236
2237 for (; i < j; i++)
2238 {
2239 if ((i & 1) == 0 && defined_local)
2240 {
2241 relocation -= pc;
2242 relocation += rel->r_addend;
2243 break;
2244 }
2245
2246 if ((i & 1) && h && h->plt.offset != MINUS_ONE)
2247 {
2248 if (rel->r_addend != 0)
2249 {
2250 fatal = (loongarch_reloc_is_fatal
2251 (info, input_bfd, input_section, rel, howto,
2252 bfd_reloc_notsupported, is_undefweak, name,
2253 "PLT shouldn't be with r_addend."));
2254 break;
2255 }
2256 relocation = sec_addr (plt) + h->plt.offset - pc;
2257 break;
2258 }
2259 }
2260 break;
2261
2262 case R_LARCH_SOP_PUSH_GPREL:
2263 unresolved_reloc = false;
2264
2265 if (rel->r_addend != 0)
2266 {
2267 fatal = (loongarch_reloc_is_fatal
2268 (info, input_bfd, input_section, rel, howto,
2269 bfd_reloc_notsupported, is_undefweak, name,
2270 "Shouldn't be with r_addend."));
2271 break;
2272 }
2273
2274 if (h != NULL)
2275 {
2276 off = h->got.offset;
2277
2278 if (off == MINUS_ONE)
2279 {
2280 fatal = (loongarch_reloc_is_fatal
2281 (info, input_bfd, input_section, rel, howto,
2282 bfd_reloc_notsupported, is_undefweak, name,
2283 "Internal: GOT entry doesn't represent."));
2284 break;
2285 }
2286
2287 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h)
2288 || (is_pic && SYMBOL_REFERENCES_LOCAL (info, h)))
2289 {
2290 /* This is actually a static link, or it is a
2291 -Bsymbolic link and the symbol is defined
2292 locally, or the symbol was forced to be local
2293 because of a version file. We must initialize
2294 this entry in the global offset table. Since the
2295 offset must always be a multiple of the word size,
2296 we use the least significant bit to record whether
2297 we have initialized it already.
2298
2299 When doing a dynamic link, we create a .rela.got
2300 relocation entry to initialize the value. This
2301 is done in the finish_dynamic_symbol routine. */
2302
2303 if (resolved_dynly)
2304 {
2305 fatal = (loongarch_reloc_is_fatal
2306 (info, input_bfd, input_section, rel, howto,
2307 bfd_reloc_dangerous, is_undefweak, name,
2308 "Internal: here shouldn't dynamic."));
2309 }
2310
2311 if (!(defined_local || resolved_to_const))
2312 {
2313 fatal = (loongarch_reloc_is_fatal
2314 (info, input_bfd, input_section, rel, howto,
2315 bfd_reloc_undefined, is_undefweak, name,
2316 "Internal: "));
2317 break;
2318 }
2319
2320 if ((off & 1) != 0)
2321 off &= ~1;
2322 else
2323 {
2324 bfd_put_NN (output_bfd, relocation, got->contents + off);
2325 h->got.offset |= 1;
2326 }
2327 }
2328 }
2329 else
2330 {
2331 if (!local_got_offsets)
2332 {
2333 fatal = (loongarch_reloc_is_fatal
2334 (info, input_bfd, input_section, rel, howto,
2335 bfd_reloc_notsupported, is_undefweak, name,
2336 "Internal: local got offsets not reporesent."));
2337 break;
2338 }
2339
2340 off = local_got_offsets[r_symndx];
2341
2342 if (off == MINUS_ONE)
2343 {
2344 fatal = (loongarch_reloc_is_fatal
2345 (info, input_bfd, input_section, rel, howto,
2346 bfd_reloc_notsupported, is_undefweak, name,
2347 "Internal: GOT entry doesn't represent."));
2348 break;
2349 }
2350
2351 /* The offset must always be a multiple of the word size.
2352 So, we can use the least significant bit to record
2353 whether we have already processed this entry. */
2354 if ((off & 1) != 0)
2355 off &= ~1;
2356 else
2357 {
2358 if (is_pic)
2359 {
2360 asection *s;
2361 Elf_Internal_Rela outrel;
2362 /* We need to generate a R_LARCH_RELATIVE reloc
2363 for the dynamic linker. */
2364 s = htab->elf.srelgot;
2365 if (!s)
2366 {
2367 fatal = (loongarch_reloc_is_fatal
2368 (info, input_bfd, input_section, rel, howto,
2369 bfd_reloc_notsupported, is_undefweak, name,
2370 "Internal: '.rel.got' not represent"));
2371 break;
2372 }
2373
2374 outrel.r_offset = sec_addr (got) + off;
2375 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2376 outrel.r_addend = relocation; /* Link-time addr. */
2377 loongarch_elf_append_rela (output_bfd, s, &outrel);
2378 }
2379
2380 bfd_put_NN (output_bfd, relocation, got->contents + off);
2381 local_got_offsets[r_symndx] |= 1;
2382 }
2383 }
2384 relocation = off;
2385 break;
2386
2387 case R_LARCH_SOP_PUSH_TLS_GOT:
2388 case R_LARCH_SOP_PUSH_TLS_GD:
2389 if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
2390 is_ie = true;
2391 unresolved_reloc = false;
2392
2393 if (rel->r_addend != 0)
2394 {
2395 fatal = (loongarch_reloc_is_fatal
2396 (info, input_bfd, input_section, rel, howto,
2397 bfd_reloc_notsupported, is_undefweak, name,
2398 "Shouldn't be with r_addend."));
2399 break;
2400 }
2401
2402
2403 if (resolved_to_const && is_undefweak && h->dynindx != -1)
2404 {
2405 /* What if undefweak? Let rtld make a decision. */
2406 resolved_to_const = resolved_local = false;
2407 resolved_dynly = true;
2408 }
2409
2410 if (resolved_to_const)
2411 {
2412 fatal = (loongarch_reloc_is_fatal
2413 (info, input_bfd, input_section, rel, howto,
2414 bfd_reloc_notsupported, is_undefweak, name,
2415 "Internal: Shouldn't be resolved to const."));
2416 break;
2417 }
2418
2419 if (h != NULL)
2420 {
2421 off = h->got.offset;
2422 h->got.offset |= 1;
2423 }
2424 else
2425 {
2426 off = local_got_offsets[r_symndx];
2427 local_got_offsets[r_symndx] |= 1;
2428 }
2429
2430 if (off == MINUS_ONE)
2431 {
2432 fatal = (loongarch_reloc_is_fatal
2433 (info, input_bfd, input_section, rel, howto,
2434 bfd_reloc_notsupported, is_undefweak, name,
2435 "Internal: TLS GOT entry doesn't represent."));
2436 break;
2437 }
2438
2439 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
2440
2441 /* If this symbol is referenced by both GD and IE TLS, the IE
2442 reference's GOT slot follows the GD reference's slots. */
2443 ie_off = 0;
2444 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
2445 ie_off = 2 * GOT_ENTRY_SIZE;
2446
2447 if ((off & 1) != 0)
2448 off &= ~1;
2449 else
2450 {
2451 bfd_vma tls_block_off = 0;
2452 Elf_Internal_Rela outrel;
2453
2454 if (resolved_local)
2455 {
2456 if (!elf_hash_table (info)->tls_sec)
2457 {
2458 fatal = (loongarch_reloc_is_fatal
2459 (info, input_bfd, input_section, rel, howto,
2460 bfd_reloc_notsupported, is_undefweak, name,
2461 "Internal: TLS sec not represent."));
2462 break;
2463 }
2464 tls_block_off =
2465 relocation - elf_hash_table (info)->tls_sec->vma;
2466 }
2467
2468 if (tls_type & GOT_TLS_GD)
2469 {
2470 outrel.r_offset = sec_addr (got) + off;
2471 outrel.r_addend = 0;
2472 bfd_put_NN (output_bfd, 0, got->contents + off);
2473 if (resolved_local && bfd_link_executable (info))
2474 bfd_put_NN (output_bfd, 1, got->contents + off);
2475 else if (resolved_local /* && !bfd_link_executable (info) */)
2476 {
2477 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
2478 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2479 &outrel);
2480 }
2481 else /* if (resolved_dynly) */
2482 {
2483 outrel.r_info =
2484 ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPMODNN);
2485 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2486 &outrel);
2487 }
2488
2489 outrel.r_offset += GOT_ENTRY_SIZE;
2490 bfd_put_NN (output_bfd, tls_block_off,
2491 got->contents + off + GOT_ENTRY_SIZE);
2492 if (resolved_local)
2493 /* DTPREL known. */;
2494 else /* if (resolved_dynly) */
2495 {
2496 outrel.r_info =
2497 ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPRELNN);
2498 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2499 &outrel);
2500 }
2501 }
2502
2503 if (tls_type & GOT_TLS_IE)
2504 {
2505 outrel.r_offset = sec_addr (got) + off + ie_off;
2506 bfd_put_NN (output_bfd, tls_block_off,
2507 got->contents + off + ie_off);
2508 if (resolved_local && bfd_link_executable (info))
2509 /* TPREL known. */;
2510 else if (resolved_local /* && !bfd_link_executable (info) */)
2511 {
2512 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
2513 outrel.r_addend = tls_block_off;
2514 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2515 &outrel);
2516 }
2517 else /* if (resolved_dynly) */
2518 {
2519 outrel.r_info =
2520 ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN);
2521 outrel.r_addend = 0;
2522 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2523 &outrel);
2524 }
2525 }
2526 }
2527
2528 relocation = off + (is_ie ? ie_off : 0);
2529 break;
2530
2531 default:
2532 break;
2533 }
2534
2535 if (fatal)
2536 break;
2537
2538 do
2539 {
2540 /* 'unresolved_reloc' means we haven't done it yet.
2541 We need help of dynamic linker to fix this memory location up. */
2542 if (!unresolved_reloc)
2543 break;
2544
2545 if (_bfd_elf_section_offset (output_bfd, info, input_section,
2546 rel->r_offset) == MINUS_ONE)
2547 /* WHY? May because it's invalid so skip checking.
2548 But why dynamic reloc a invalid section? */
2549 break;
2550
2551 if (input_section->output_section->flags & SEC_DEBUGGING)
2552 {
2553 fatal = (loongarch_reloc_is_fatal
2554 (info, input_bfd, input_section, rel, howto,
2555 bfd_reloc_dangerous, is_undefweak, name,
2556 "Seems dynamic linker not process "
2557 "sections 'SEC_DEBUGGING'."));
2558 }
2559 if (!is_dyn)
2560 break;
2561
2562 if ((info->flags & DF_TEXTREL) == 0)
2563 if (input_section->output_section->flags & SEC_READONLY)
2564 info->flags |= DF_TEXTREL;
2565 }
2566 while (0);
2567
2568 if (fatal)
2569 break;
2570
2571 loongarch_record_one_reloc (input_bfd, input_section, r_type,
2572 rel->r_offset, sym, h, rel->r_addend);
2573
2574 if (r != bfd_reloc_continue)
2575 r = perform_relocation (rel, input_section, howto, relocation,
2576 input_bfd, contents);
2577
2578 switch (r)
2579 {
2580 case bfd_reloc_dangerous:
2581 case bfd_reloc_continue:
2582 case bfd_reloc_ok:
2583 continue;
2584
2585 case bfd_reloc_overflow:
2586 /* Overflow value can't be filled in. */
2587 loongarch_dump_reloc_record (info->callbacks->info);
2588 info->callbacks->reloc_overflow
2589 (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
2590 input_bfd, input_section, rel->r_offset);
2591 break;
2592
2593 case bfd_reloc_outofrange:
2594 /* Stack state incorrect. */
2595 loongarch_dump_reloc_record (info->callbacks->info);
2596 info->callbacks->info
2597 ("%X%H: Internal stack state is incorrect.\n"
2598 "Want to push to full stack or pop from empty stack?\n",
2599 input_bfd, input_section, rel->r_offset);
2600 break;
2601
2602 case bfd_reloc_notsupported:
2603 info->callbacks->info ("%X%H: Unknown relocation type.\n", input_bfd,
2604 input_section, rel->r_offset);
2605 break;
2606
2607 default:
2608 info->callbacks->info ("%X%H: Internal: unknown error.\n", input_bfd,
2609 input_section, rel->r_offset);
2610 break;
2611 }
2612
2613 fatal = true;
2614 break;
2615 }
2616
2617 return !fatal;
2618}
2619
2620/* Finish up dynamic symbol handling. We set the contents of various
2621 dynamic sections here. */
2622
2623static bool
2624loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
2625 struct bfd_link_info *info,
2626 struct elf_link_hash_entry *h,
2627 Elf_Internal_Sym *sym)
2628{
2629 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2630 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
2631 asection *plt = NULL;
2632
2633 if (h->plt.offset != MINUS_ONE)
2634 {
2635 size_t i, plt_idx;
2636 asection *gotplt, *relplt;
2637 bfd_vma got_address;
2638 uint32_t plt_entry[PLT_ENTRY_INSNS];
2639 bfd_byte *loc;
2640 Elf_Internal_Rela rela;
2641
2642 plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
2643
2644 /* One of '.plt' and '.iplt' represents. */
2645 BFD_ASSERT (!!htab->elf.splt ^ !!htab->elf.iplt);
2646
2647 if (htab->elf.splt)
2648 {
2649 BFD_ASSERT ((h->type == STT_GNU_IFUNC
2650 && SYMBOL_REFERENCES_LOCAL (info, h))
2651 || h->dynindx != -1);
2652
2653 plt = htab->elf.splt;
2654 gotplt = htab->elf.sgotplt;
2655 relplt = htab->elf.srelplt;
2656 got_address =
2657 sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
2658 }
2659 else /* if (htab->elf.iplt) */
2660 {
2661 BFD_ASSERT (h->type == STT_GNU_IFUNC
2662 && SYMBOL_REFERENCES_LOCAL (info, h));
2663
2664 plt = htab->elf.iplt;
2665 gotplt = htab->elf.igotplt;
2666 relplt = htab->elf.irelplt;
2667 got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
2668 }
2669
2670 /* Find out where the .plt entry should go. */
2671 loc = plt->contents + h->plt.offset;
2672
2673 /* Fill in the PLT entry itself. */
2674 if (!loongarch_make_plt_entry (got_address,
2675 sec_addr (plt) + h->plt.offset,
2676 plt_entry))
2677 return false;
2678
2679 for (i = 0; i < PLT_ENTRY_INSNS; i++)
2680 bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
2681
2682 /* Fill in the initial value of the .got.plt entry. */
2683 loc = gotplt->contents + (got_address - sec_addr (gotplt));
2684 bfd_put_NN (output_bfd, sec_addr (plt), loc);
2685
2686 rela.r_offset = got_address;
2687 if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
2688 {
2689 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2690 rela.r_addend = (h->root.u.def.value
2691 + h->root.u.def.section->output_section->vma
2692 + h->root.u.def.section->output_offset);
2693 }
2694 else
2695 {
2696 /* Fill in the entry in the .rela.plt section. */
2697 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
2698 rela.r_addend = 0;
2699 }
2700
2701 loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
2702 bed->s->swap_reloca_out (output_bfd, &rela, loc);
2703
2704 if (!h->def_regular)
2705 {
2706 /* Mark the symbol as undefined, rather than as defined in
2707 the .plt section. Leave the value alone. */
2708 sym->st_shndx = SHN_UNDEF;
2709 /* If the symbol is weak, we do need to clear the value.
2710 Otherwise, the PLT entry would provide a definition for
2711 the symbol even if the symbol wasn't defined anywhere,
2712 and so the symbol would never be NULL. */
2713 if (!h->ref_regular_nonweak)
2714 sym->st_value = 0;
2715 }
2716 }
2717
2718 if (h->got.offset != MINUS_ONE
2719 /* TLS got entry have been handled in elf_relocate_section. */
2720 && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
2721 /* have allocated got entry but not allocated rela before. */
2722 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
2723 {
2724 asection *sgot, *srela;
2725 Elf_Internal_Rela rela;
2726 bfd_vma off = h->got.offset & ~(bfd_vma) 1;
2727
2728 /* This symbol has an entry in the GOT. Set it up. */
2729
2730 sgot = htab->elf.sgot;
2731 srela = htab->elf.srelgot;
2732 BFD_ASSERT (sgot && srela);
2733
2734 rela.r_offset = sec_addr (sgot) + off;
2735
2736 if (h->type == STT_GNU_IFUNC)
2737 {
2738 if (elf_hash_table (info)->dynamic_sections_created
2739 && SYMBOL_REFERENCES_LOCAL (info, h))
2740 {
2741 asection *sec = h->root.u.def.section;
2742 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2743 rela.r_addend = (h->root.u.def.value + sec->output_section->vma
2744 + sec->output_offset);
2745 bfd_put_NN (output_bfd, 0, sgot->contents + off);
2746 }
2747 else
2748 {
2749 BFD_ASSERT (plt);
2750 rela.r_info
2751 = ELFNN_R_INFO (0, (bfd_link_pic (info)
2752 ? R_LARCH_RELATIVE : R_LARCH_NONE));
2753 rela.r_addend =
2754 plt->output_section->vma + plt->output_offset + h->plt.offset;
2755 bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
2756 }
2757 }
2758 else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
2759 {
2760 BFD_ASSERT (h->got.offset & 1 /* Has been filled in addr. */);
2761 asection *sec = h->root.u.def.section;
2762 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2763 rela.r_addend = (h->root.u.def.value + sec->output_section->vma
2764 + sec->output_offset);
2765 }
2766 else
2767 {
2768 BFD_ASSERT ((h->got.offset & 1) == 0);
2769 BFD_ASSERT (h->dynindx != -1);
2770 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
2771 rela.r_addend = 0;
2772 }
2773
2774 loongarch_elf_append_rela (output_bfd, srela, &rela);
2775 }
2776
2777 if (h->needs_copy)
2778 {
2779 Elf_Internal_Rela rela;
2780 asection *s;
2781
2782 /* This symbols needs a copy reloc. Set it up. */
2783 BFD_ASSERT (h->dynindx != -1);
2784
2785 rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value;
2786 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY);
2787 rela.r_addend = 0;
2788 if (h->root.u.def.section == htab->elf.sdynrelro)
2789 s = htab->elf.sreldynrelro;
2790 else
2791 s = htab->elf.srelbss;
2792 loongarch_elf_append_rela (output_bfd, s, &rela);
2793 }
2794
2795 /* Mark some specially defined symbols as absolute. */
2796 if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
2797 sym->st_shndx = SHN_ABS;
2798
2799 return true;
2800}
2801
2802/* Finish up the dynamic sections. */
2803
2804static bool
2805loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
2806 asection *sdyn)
2807{
2808 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2809 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
2810 size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
2811 bfd_byte *dyncon, *dynconend;
2812
2813 dynconend = sdyn->contents + sdyn->size;
2814 for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
2815 {
2816 Elf_Internal_Dyn dyn;
2817 asection *s;
2818 int skipped = 0;
2819
2820 bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
2821
2822 switch (dyn.d_tag)
2823 {
2824 case DT_PLTGOT:
2825 s = htab->elf.sgotplt;
2826 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
2827 break;
2828 case DT_JMPREL:
2829 s = htab->elf.srelplt;
2830 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
2831 break;
2832 case DT_PLTRELSZ:
2833 s = htab->elf.srelplt;
2834 dyn.d_un.d_val = s->size;
2835 break;
2836 case DT_TEXTREL:
2837 if ((info->flags & DF_TEXTREL) == 0)
2838 skipped = 1;
2839 break;
2840 case DT_FLAGS:
2841 if ((info->flags & DF_TEXTREL) == 0)
2842 dyn.d_un.d_val &= ~DF_TEXTREL;
2843 break;
2844 }
2845 if (skipped)
2846 skipped_size += dynsize;
2847 else
2848 bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
2849 }
2850 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
2851 memset (dyncon - skipped_size, 0, skipped_size);
2852 return true;
2853}
2854
2855/* Finish up local dynamic symbol handling. We set the contents of
2856 various dynamic sections here. */
2857
2858static bool
2859elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
2860{
2861 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
2862 struct bfd_link_info *info = (struct bfd_link_info *) inf;
2863
2864 return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
2865}
2866
2867static bool
2868loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
2869 struct bfd_link_info *info)
2870{
2871 bfd *dynobj;
2872 asection *sdyn, *plt, *gotplt = NULL;
2873 struct loongarch_elf_link_hash_table *htab;
2874
2875 htab = loongarch_elf_hash_table (info);
2876 BFD_ASSERT (htab);
2877 dynobj = htab->elf.dynobj;
2878 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
2879
2880 if (elf_hash_table (info)->dynamic_sections_created)
2881 {
2882 BFD_ASSERT (htab->elf.splt && sdyn);
2883
2884 if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
2885 return false;
2886 }
2887
2888 if ((plt = htab->elf.splt))
2889 gotplt = htab->elf.sgotplt;
2890 else if ((plt = htab->elf.iplt))
2891 gotplt = htab->elf.igotplt;
2892
2893 if (plt && 0 < plt->size)
2894 {
2895 size_t i;
2896 uint32_t plt_header[PLT_HEADER_INSNS];
2897 if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
2898 plt_header))
2899 return false;
2900
2901 for (i = 0; i < PLT_HEADER_INSNS; i++)
2902 bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
2903
2904 elf_section_data (plt->output_section)->this_hdr.sh_entsize =
2905 PLT_ENTRY_SIZE;
2906 }
2907
2908 if (htab->elf.sgotplt)
2909 {
2910 asection *output_section = htab->elf.sgotplt->output_section;
2911
2912 if (bfd_is_abs_section (output_section))
2913 {
2914 _bfd_error_handler (_("discarded output section: `%pA'"),
2915 htab->elf.sgotplt);
2916 return false;
2917 }
2918
2919 if (0 < htab->elf.sgotplt->size)
2920 {
2921 /* Write the first two entries in .got.plt, needed for the dynamic
2922 linker. */
2923 bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
2924
2925 bfd_put_NN (output_bfd, (bfd_vma) 0,
2926 htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
2927 }
2928
2929 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
2930 }
2931
2932 if (htab->elf.sgot)
2933 {
2934 asection *output_section = htab->elf.sgot->output_section;
2935
2936 if (0 < htab->elf.sgot->size)
2937 {
2938 /* Set the first entry in the global offset table to the address of
2939 the dynamic section. */
2940 bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
2941 bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
2942 }
2943
2944 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
2945 }
2946
2947 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
2948 htab_traverse (htab->loc_hash_table,
2949 (void *) elfNN_loongarch_finish_local_dynamic_symbol, info);
2950
2951 return true;
2952}
2953
2954/* Return address for Ith PLT stub in section PLT, for relocation REL
2955 or (bfd_vma) -1 if it should not be included. */
2956
2957static bfd_vma
2958loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
2959 const arelent *rel ATTRIBUTE_UNUSED)
2960{
2961 return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
2962}
2963
2964static enum elf_reloc_type_class
2965loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
2966 const asection *rel_sec ATTRIBUTE_UNUSED,
2967 const Elf_Internal_Rela *rela)
2968{
2969 struct loongarch_elf_link_hash_table *htab;
2970 htab = loongarch_elf_hash_table (info);
2971
2972 if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
2973 {
2974 /* Check relocation against STT_GNU_IFUNC symbol if there are
2975 dynamic symbols. */
2976 bfd *abfd = info->output_bfd;
2977 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
2978 unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
2979 if (r_symndx != STN_UNDEF)
2980 {
2981 Elf_Internal_Sym sym;
2982 if (!bed->s->swap_symbol_in (abfd,
2983 htab->elf.dynsym->contents
2984 + r_symndx * bed->s->sizeof_sym,
2985 0, &sym))
2986 {
2987 /* xgettext:c-format */
2988 _bfd_error_handler (_("%pB symbol number %lu references"
2989 " nonexistent SHT_SYMTAB_SHNDX section"),
2990 abfd, r_symndx);
2991 /* Ideally an error class should be returned here. */
2992 }
2993 else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
2994 return reloc_class_ifunc;
2995 }
2996 }
2997
2998 switch (ELFNN_R_TYPE (rela->r_info))
2999 {
3000 case R_LARCH_IRELATIVE:
3001 return reloc_class_ifunc;
3002 case R_LARCH_RELATIVE:
3003 return reloc_class_relative;
3004 case R_LARCH_JUMP_SLOT:
3005 return reloc_class_plt;
3006 case R_LARCH_COPY:
3007 return reloc_class_copy;
3008 default:
3009 return reloc_class_normal;
3010 }
3011}
3012
3013/* Copy the extra info we tack onto an elf_link_hash_entry. */
3014
3015static void
3016loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
3017 struct elf_link_hash_entry *dir,
3018 struct elf_link_hash_entry *ind)
3019{
3020 struct loongarch_elf_link_hash_entry *edir, *eind;
3021
3022 edir = (struct loongarch_elf_link_hash_entry *) dir;
3023 eind = (struct loongarch_elf_link_hash_entry *) ind;
3024
3025 if (eind->dyn_relocs != NULL)
3026 {
3027 if (edir->dyn_relocs != NULL)
3028 {
3029 struct elf_dyn_relocs **pp;
3030 struct elf_dyn_relocs *p;
3031
3032 /* Add reloc counts against the indirect sym to the direct sym
3033 list. Merge any entries against the same section. */
3034 for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
3035 {
3036 struct elf_dyn_relocs *q;
3037
3038 for (q = edir->dyn_relocs; q != NULL; q = q->next)
3039 if (q->sec == p->sec)
3040 {
3041 q->pc_count += p->pc_count;
3042 q->count += p->count;
3043 *pp = p->next;
3044 break;
3045 }
3046 if (q == NULL)
3047 pp = &p->next;
3048 }
3049 *pp = edir->dyn_relocs;
3050 }
3051
3052 edir->dyn_relocs = eind->dyn_relocs;
3053 eind->dyn_relocs = NULL;
3054 }
3055
3056 if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
3057 {
3058 edir->tls_type = eind->tls_type;
3059 eind->tls_type = GOT_UNKNOWN;
3060 }
3061 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3062}
3063
3064#define PRSTATUS_SIZE 0x1d8
3065#define PRSTATUS_OFFSET_PR_CURSIG 0xc
3066#define PRSTATUS_OFFSET_PR_PID 0x20
3067#define ELF_GREGSET_T_SIZE 0x168
3068#define PRSTATUS_OFFSET_PR_REG 0x70
3069
3070/* Support for core dump NOTE sections. */
3071
3072static bool
3073loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
3074{
3075 switch (note->descsz)
3076 {
3077 default:
3078 return false;
3079
3080 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
3081 case PRSTATUS_SIZE:
3082 /* pr_cursig */
3083 elf_tdata (abfd)->core->signal =
3084 bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
3085
3086 /* pr_pid */
3087 elf_tdata (abfd)->core->lwpid =
3088 bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
3089 break;
3090 }
3091
3092 /* Make a ".reg/999" section. */
3093 return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
3094 note->descpos
3095 + PRSTATUS_OFFSET_PR_REG);
3096}
3097
3098#define PRPSINFO_SIZE 0x88
3099#define PRPSINFO_OFFSET_PR_PID 0x18
3100#define PRPSINFO_OFFSET_PR_FNAME 0x28
3101#define PRPSINFO_SIZEOF_PR_FNAME 0x10
3102#define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
3103#define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
3104
3105
3106static bool
3107loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
3108{
3109 switch (note->descsz)
3110 {
3111 default:
3112 return false;
3113
3114 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
3115 case PRPSINFO_SIZE:
3116 /* pr_pid */
3117 elf_tdata (abfd)->core->pid =
3118 bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
3119
3120 /* pr_fname */
3121 elf_tdata (abfd)->core->program =
3122 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
3123 PRPSINFO_SIZEOF_PR_FNAME);
3124
3125 /* pr_psargs */
3126 elf_tdata (abfd)->core->command =
3127 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
3128 PRPSINFO_SIZEOF_PR_PS_ARGS);
3129 break;
3130 }
3131
3132 /* Note that for some reason, a spurious space is tacked
3133 onto the end of the args in some (at least one anyway)
3134 implementations, so strip it off if it exists. */
3135
3136 {
3137 char *command = elf_tdata (abfd)->core->command;
3138 int n = strlen (command);
3139
3140 if (0 < n && command[n - 1] == ' ')
3141 command[n - 1] = '\0';
3142 }
3143
3144 return true;
3145}
3146
3147/* Set the right mach type. */
3148static bool
3149loongarch_elf_object_p (bfd *abfd)
3150{
3151 /* There are only two mach types in LoongArch currently. */
3152 if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
3153 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
3154 else
3155 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
3156 return true;
3157}
3158
3159static asection *
3160loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
3161 Elf_Internal_Rela *rel,
3162 struct elf_link_hash_entry *h,
3163 Elf_Internal_Sym *sym)
3164{
3165 if (h != NULL)
3166 switch (ELFNN_R_TYPE (rel->r_info))
3167 {
3168 case R_LARCH_GNU_VTINHERIT:
3169 case R_LARCH_GNU_VTENTRY:
3170 return NULL;
3171 }
3172
3173 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
3174}
3175
3176#define TARGET_LITTLE_SYM loongarch_elfNN_vec
3177#define TARGET_LITTLE_NAME "elfNN-loongarch"
3178#define ELF_ARCH bfd_arch_loongarch
3179#define ELF_TARGET_ID LARCH_ELF_DATA
3180#define ELF_MACHINE_CODE EM_LOONGARCH
3181#define ELF_MAXPAGESIZE 0x4000
3182#define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
3183#define bfd_elfNN_bfd_link_hash_table_create \
3184 loongarch_elf_link_hash_table_create
3185#define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
3186#define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
3187#define elf_info_to_howto loongarch_info_to_howto_rela
3188#define bfd_elfNN_bfd_merge_private_bfd_data \
3189 elfNN_loongarch_merge_private_bfd_data
3190
3191#define elf_backend_reloc_type_class loongarch_reloc_type_class
3192#define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
3193#define elf_backend_create_dynamic_sections \
3194 loongarch_elf_create_dynamic_sections
3195#define elf_backend_check_relocs loongarch_elf_check_relocs
3196#define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
3197#define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
3198#define elf_backend_relocate_section loongarch_elf_relocate_section
3199#define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
3200#define elf_backend_finish_dynamic_sections \
3201 loongarch_elf_finish_dynamic_sections
3202#define elf_backend_object_p loongarch_elf_object_p
3203#define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
3204#define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
3205#define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
3206#define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
3207
3208#include "elfNN-target.h"