]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elfnn-loongarch.c
LoongArch bfd support
[thirdparty/binutils-gdb.git] / bfd / elfnn-loongarch.c
1 /* LoongArch-specific support for NN-bit ELF.
2 Copyright (C) 2021 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
20
21 #include "ansidecl.h"
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #define ARCH_SIZE NN
26 #include "elf-bfd.h"
27 #include "objalloc.h"
28 #include "elf/loongarch.h"
29 #include "elfxx-loongarch.h"
30
31 static bool
32 loongarch_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. */
41 struct 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
59 struct _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
83 struct 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
142 static bool
143 loongarch_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
194 static bool
195 loongarch_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
221 static struct bfd_hash_entry *
222 link_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
253 static hashval_t
254 elfNN_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
262 static int
263 elfNN_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. */
272 static struct elf_link_hash_entry *
273 elfNN_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
322 static void
323 elfNN_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
338 static struct bfd_link_hash_table *
339 loongarch_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
374 static bool
375 elfNN_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. */
404 if ((out_flags ^ in_flags) & EF_LOONGARCH_ABI)
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
419 static bool
420 loongarch_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
478 static bool
479 loongarch_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
504 static bool
505 loongarch_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
569 static bool
570 loongarch_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
835 static asection *
836 readonly_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. */
855 static bool
856 loongarch_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
984 static bool
985 allocate_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
1132 static bool
1133 elfNN_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
1147 static bool
1148 maybe_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
1171 static bool
1172 loongarch_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
1394 static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
1395 static size_t larch_stack_top = 0;
1396
1397 static bfd_reloc_status_type
1398 loongarch_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
1406 static bfd_reloc_status_type
1407 loongarch_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
1416 static bfd_reloc_status_type
1417 loongarch_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
1426 static void
1427 loongarch_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. */
1438 static bfd_reloc_status_type
1439 loongarch_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
1449
1450 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
1451 ({ \
1452 bfd_reloc_status_type ret = loongarch_pop (&op2); \
1453 if (ret == bfd_reloc_ok) \
1454 { \
1455 ret = loongarch_pop (&op1); \
1456 if (ret == bfd_reloc_ok) \
1457 ret = loongarch_push (op3); \
1458 } \
1459 ret; \
1460 })
1461
1462 #define LARCH_RELOC_UINT32_BIT_MASK(bitsize) \
1463 (~((0x1U << (bitsize)) - 1))
1464
1465 static bfd_reloc_status_type
1466 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
1467 const asection *input_section ATTRIBUTE_UNUSED,
1468 reloc_howto_type *howto, bfd *input_bfd,
1469 bfd_byte *contents, int64_t op,
1470 bool is_signed)
1471 {
1472 /* Check op low bits if rightshift != 0, before rightshift */
1473 if (howto->rightshift
1474 && (((0x1U << howto->rightshift) - 1) & op))
1475 return bfd_reloc_overflow;
1476
1477 uint32_t imm = (uint32_t)(int32_t)(op >> howto->rightshift);
1478
1479 if (is_signed)
1480 {
1481 if (op >= 0)
1482 {
1483 if (LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1) & imm)
1484 return bfd_reloc_overflow;
1485 }
1486 else
1487 {
1488 if ((LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1) & imm)
1489 != LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1))
1490 return bfd_reloc_overflow;
1491 }
1492 }
1493 else
1494 {
1495 if (LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize) & imm)
1496 return bfd_reloc_overflow;
1497 }
1498
1499 int bits = bfd_get_reloc_size (howto) * 8;
1500 uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
1501
1502 imm = imm & ((0x1U << howto->bitsize) - 1);
1503 imm <<= howto->bitpos;
1504 insn = ((insn & howto->src_mask)
1505 | ((insn & (~(uint32_t) howto->dst_mask)) | imm));
1506 bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
1507
1508 return bfd_reloc_ok;
1509 }
1510
1511 /* Emplace a static relocation. */
1512
1513 static bfd_reloc_status_type
1514 perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
1515 reloc_howto_type *howto, bfd_vma value,
1516 bfd *input_bfd, bfd_byte *contents)
1517 {
1518 uint32_t insn1;
1519 int64_t opr1, opr2, opr3;
1520 bfd_reloc_status_type r = bfd_reloc_ok;
1521 int bits = bfd_get_reloc_size (howto) * 8;
1522
1523
1524 switch (ELFNN_R_TYPE (rel->r_info))
1525 {
1526 case R_LARCH_SOP_PUSH_PCREL:
1527 case R_LARCH_SOP_PUSH_ABSOLUTE:
1528 case R_LARCH_SOP_PUSH_GPREL:
1529 case R_LARCH_SOP_PUSH_TLS_TPREL:
1530 case R_LARCH_SOP_PUSH_TLS_GOT:
1531 case R_LARCH_SOP_PUSH_TLS_GD:
1532 case R_LARCH_SOP_PUSH_PLT_PCREL:
1533 r = loongarch_push (value);
1534 break;
1535
1536 case R_LARCH_SOP_PUSH_DUP:
1537 r = loongarch_pop (&opr1);
1538 if (r == bfd_reloc_ok)
1539 {
1540 r = loongarch_push (opr1);
1541 if (r == bfd_reloc_ok)
1542 r = loongarch_push (opr1);
1543 }
1544 break;
1545
1546 case R_LARCH_SOP_ASSERT:
1547 r = loongarch_pop (&opr1);
1548 if (r != bfd_reloc_ok || !opr1)
1549 r = bfd_reloc_notsupported;
1550 break;
1551
1552 case R_LARCH_SOP_NOT:
1553 r = loongarch_pop (&opr1);
1554 if (r == bfd_reloc_ok)
1555 r = loongarch_push (!opr1);
1556 break;
1557
1558 case R_LARCH_SOP_SUB:
1559 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
1560 break;
1561
1562 case R_LARCH_SOP_SL:
1563 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
1564 break;
1565
1566 case R_LARCH_SOP_SR:
1567 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
1568 break;
1569
1570 case R_LARCH_SOP_AND:
1571 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
1572 break;
1573
1574 case R_LARCH_SOP_ADD:
1575 r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
1576 break;
1577
1578 case R_LARCH_SOP_IF_ELSE:
1579 r = loongarch_pop (&opr3);
1580 if (r == bfd_reloc_ok)
1581 {
1582 r = loongarch_pop (&opr2);
1583 if (r == bfd_reloc_ok)
1584 {
1585 r = loongarch_pop (&opr1);
1586 if (r == bfd_reloc_ok)
1587 r = loongarch_push (opr1 ? opr2 : opr3);
1588 }
1589 }
1590 break;
1591
1592 case R_LARCH_SOP_POP_32_S_10_5:
1593 case R_LARCH_SOP_POP_32_S_10_12:
1594 case R_LARCH_SOP_POP_32_S_10_16:
1595 case R_LARCH_SOP_POP_32_S_10_16_S2:
1596 case R_LARCH_SOP_POP_32_S_5_20:
1597 r = loongarch_pop (&opr1);
1598 if (r != bfd_reloc_ok)
1599 break;
1600 r = loongarch_check_offset (rel, input_section);
1601 if (r != bfd_reloc_ok)
1602 break;
1603
1604 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
1605 howto, input_bfd,
1606 contents, opr1, true);
1607 break;
1608
1609 case R_LARCH_SOP_POP_32_U_10_12:
1610 r = loongarch_pop (&opr1);
1611 if (r != bfd_reloc_ok)
1612 break;
1613 r = loongarch_check_offset (rel, input_section);
1614 if (r != bfd_reloc_ok)
1615 break;
1616
1617 r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
1618 howto, input_bfd,
1619 contents, opr1, false);
1620 break;
1621
1622 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1623 {
1624 r = loongarch_pop (&opr1);
1625 if (r != bfd_reloc_ok)
1626 break;
1627
1628 if ((opr1 & 0x3) != 0)
1629 {
1630 r = bfd_reloc_overflow;
1631 break;
1632 }
1633
1634 uint32_t imm = opr1 >> howto->rightshift;
1635 if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU)))
1636 {
1637 r = bfd_reloc_overflow;
1638 break;
1639 }
1640
1641 r = loongarch_check_offset (rel, input_section);
1642 if (r != bfd_reloc_ok)
1643 break;
1644
1645 insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1646 insn1 = ((insn1 & howto->src_mask)
1647 | ((imm & 0xffffU) << 10)
1648 | ((imm & 0x1f0000U) >> 16));
1649 bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
1650 break;
1651 }
1652
1653 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1654 {
1655 r = loongarch_pop (&opr1);
1656 if (r != bfd_reloc_ok)
1657 break;
1658
1659 if ((opr1 & 0x3) != 0)
1660 {
1661 r = bfd_reloc_overflow;
1662 break;
1663 }
1664
1665 uint32_t imm = opr1 >> howto->rightshift;
1666 if ((imm & (~0x1ffffffU)) && (imm & (~0x1ffffffU)) != (~0x1ffffffU))
1667 {
1668 r = bfd_reloc_overflow;
1669 break;
1670 }
1671
1672 r = loongarch_check_offset (rel, input_section);
1673 if (r != bfd_reloc_ok)
1674 break;
1675
1676 insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1677 insn1 = ((insn1 & howto->src_mask)
1678 | ((imm & 0xffffU) << 10)
1679 | ((imm & 0x3ff0000U) >> 16));
1680 bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
1681 break;
1682 }
1683
1684 case R_LARCH_SOP_POP_32_U:
1685 r = loongarch_pop (&opr1);
1686 if (r != bfd_reloc_ok)
1687 break;
1688 if ((uint64_t)opr1 & ~(uint64_t) 0xffffffff)
1689 r = bfd_reloc_overflow;
1690 if (r != bfd_reloc_ok)
1691 break;
1692 r = loongarch_check_offset (rel, input_section);
1693 if (r != bfd_reloc_ok)
1694 break;
1695
1696 bfd_put (bits, input_bfd, opr1, contents + rel->r_offset);
1697 break;
1698
1699 case R_LARCH_TLS_DTPREL32:
1700 case R_LARCH_32:
1701 case R_LARCH_TLS_DTPREL64:
1702 case R_LARCH_64:
1703 r = loongarch_check_offset (rel, input_section);
1704 if (r != bfd_reloc_ok)
1705 break;
1706
1707 bfd_put (bits, input_bfd, value, contents + rel->r_offset);
1708 break;
1709
1710 case R_LARCH_ADD8:
1711 case R_LARCH_ADD16:
1712 case R_LARCH_ADD24:
1713 case R_LARCH_ADD32:
1714 case R_LARCH_ADD64:
1715 r = loongarch_check_offset (rel, input_section);
1716 if (r != bfd_reloc_ok)
1717 break;
1718
1719 opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1720 bfd_put (bits, input_bfd, opr1 + value, contents + rel->r_offset);
1721 break;
1722
1723 case R_LARCH_SUB8:
1724 case R_LARCH_SUB16:
1725 case R_LARCH_SUB24:
1726 case R_LARCH_SUB32:
1727 case R_LARCH_SUB64:
1728 r = loongarch_check_offset (rel, input_section);
1729 if (r != bfd_reloc_ok)
1730 break;
1731
1732 opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
1733 bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
1734 break;
1735
1736 default:
1737 r = bfd_reloc_notsupported;
1738 }
1739 return r;
1740 }
1741
1742 #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
1743 static struct
1744 {
1745 bfd *bfd;
1746 asection *section;
1747 bfd_vma r_offset;
1748 int r_type;
1749 bfd_vma relocation;
1750 Elf_Internal_Sym *sym;
1751 struct elf_link_hash_entry *h;
1752 bfd_vma addend;
1753 int64_t top_then;
1754 } larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
1755 static size_t larch_reloc_queue_head = 0;
1756 static size_t larch_reloc_queue_tail = 0;
1757
1758 static const char *
1759 loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
1760 Elf_Internal_Sym *sym)
1761 {
1762 const char *ret = NULL;
1763 if (sym)
1764 ret = bfd_elf_string_from_elf_section (input_bfd,
1765 elf_symtab_hdr (input_bfd).sh_link,
1766 sym->st_name);
1767 else if (h)
1768 ret = h->root.root.string;
1769
1770 if (ret == NULL || *ret == '\0')
1771 ret = "<nameless>";
1772 return ret;
1773 }
1774
1775 static void
1776 loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
1777 bfd_vma r_offset, Elf_Internal_Sym *sym,
1778 struct elf_link_hash_entry *h, bfd_vma addend)
1779 {
1780 if ((larch_reloc_queue_head == 0
1781 && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
1782 || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
1783 larch_reloc_queue_head =
1784 (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
1785 larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
1786 larch_reloc_queue[larch_reloc_queue_tail].section = section;
1787 larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
1788 larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
1789 larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
1790 larch_reloc_queue[larch_reloc_queue_tail].h = h;
1791 larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
1792 loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
1793 larch_reloc_queue_tail =
1794 (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
1795 }
1796
1797 static void
1798 loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
1799 {
1800 size_t i = larch_reloc_queue_head;
1801 bfd *a_bfd = NULL;
1802 asection *section = NULL;
1803 bfd_vma r_offset = 0;
1804 int inited = 0;
1805 p ("Dump relocate record:\n");
1806 p ("stack top\t\trelocation name\t\tsymbol");
1807 while (i != larch_reloc_queue_tail)
1808 {
1809 if (a_bfd != larch_reloc_queue[i].bfd
1810 || section != larch_reloc_queue[i].section
1811 || r_offset != larch_reloc_queue[i].r_offset)
1812 {
1813 a_bfd = larch_reloc_queue[i].bfd;
1814 section = larch_reloc_queue[i].section;
1815 r_offset = larch_reloc_queue[i].r_offset;
1816 p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
1817 larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
1818 }
1819
1820 if (!inited)
1821 inited = 1, p ("...\n");
1822
1823 reloc_howto_type *howto =
1824 loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
1825 larch_reloc_queue[i].r_type);
1826 p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
1827 howto ? howto->name : "<unknown reloc>",
1828 loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
1829 larch_reloc_queue[i].sym));
1830
1831 long addend = larch_reloc_queue[i].addend;
1832 if (addend < 0)
1833 p (" - %ld", -addend);
1834 else if (0 < addend)
1835 p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
1836
1837 p ("\n");
1838 i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
1839 }
1840 p ("\n"
1841 "-- Record dump end --\n\n");
1842 }
1843
1844
1845 static bool
1846 loongarch_reloc_is_fatal (struct bfd_link_info *info,
1847 bfd *input_bfd,
1848 asection *input_section,
1849 Elf_Internal_Rela *rel,
1850 reloc_howto_type *howto,
1851 bfd_reloc_status_type rtype,
1852 bool is_undefweak,
1853 const char *name,
1854 const char *msg)
1855 {
1856 bool fatal = true;
1857 switch (rtype)
1858 {
1859 /* 'dangerous' means we do it but can't promise it's ok
1860 'unsupport' means out of ability of relocation type
1861 'undefined' means we can't deal with the undefined symbol. */
1862 case bfd_reloc_undefined:
1863 info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
1864 rel->r_offset, true);
1865 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1866 input_bfd, input_section, rel->r_offset,
1867 howto->name,
1868 is_undefweak ? "[undefweak] " : "", name, msg);
1869 break;
1870 case bfd_reloc_dangerous:
1871 info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
1872 input_bfd, input_section, rel->r_offset,
1873 howto->name,
1874 is_undefweak ? "[undefweak] " : "", name, msg);
1875 fatal = false;
1876 break;
1877 case bfd_reloc_notsupported:
1878 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
1879 input_bfd, input_section, rel->r_offset,
1880 howto->name,
1881 is_undefweak ? "[undefweak] " : "", name, msg);
1882 break;
1883 default:
1884 break;
1885 }
1886 return fatal;
1887 }
1888
1889
1890
1891
1892 static int
1893 loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
1894 bfd *input_bfd, asection *input_section,
1895 bfd_byte *contents, Elf_Internal_Rela *relocs,
1896 Elf_Internal_Sym *local_syms,
1897 asection **local_sections)
1898 {
1899 Elf_Internal_Rela *rel;
1900 Elf_Internal_Rela *relend;
1901 bool fatal = false;
1902 asection *sreloc = elf_section_data (input_section)->sreloc;
1903 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
1904 Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
1905 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
1906 bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
1907 bool is_pic = bfd_link_pic (info);
1908 bool is_dyn = elf_hash_table (info)->dynamic_sections_created;
1909 asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
1910 asection *got = htab->elf.sgot;
1911
1912 relend = relocs + input_section->reloc_count;
1913 for (rel = relocs; rel < relend; rel++)
1914 {
1915 int r_type = ELFNN_R_TYPE (rel->r_info);
1916 unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
1917 bfd_vma pc = sec_addr (input_section) + rel->r_offset;
1918 reloc_howto_type *howto = NULL;
1919 asection *sec = NULL;
1920 Elf_Internal_Sym *sym = NULL;
1921 struct elf_link_hash_entry *h = NULL;
1922 const char *name;
1923 bfd_reloc_status_type r = bfd_reloc_ok;
1924 bool is_ie, is_undefweak, unresolved_reloc, defined_local;
1925 bool resolved_local, resolved_dynly, resolved_to_const;
1926 char tls_type;
1927 bfd_vma relocation;
1928 bfd_vma off, ie_off;
1929 int i, j;
1930
1931 howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
1932 if (howto == NULL || r_type == R_LARCH_GNU_VTINHERIT
1933 || r_type == R_LARCH_GNU_VTENTRY)
1934 continue;
1935
1936 /* This is a final link. */
1937 if (r_symndx < symtab_hdr->sh_info)
1938 {
1939 is_undefweak = false;
1940 unresolved_reloc = false;
1941 sym = local_syms + r_symndx;
1942 sec = local_sections[r_symndx];
1943 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1944
1945 /* Relocate against local STT_GNU_IFUNC symbol. */
1946 if (!bfd_link_relocatable (info)
1947 && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
1948 {
1949 h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
1950 false);
1951 if (h == NULL)
1952 abort ();
1953
1954 /* Set STT_GNU_IFUNC symbol value. */
1955 h->root.u.def.value = sym->st_value;
1956 h->root.u.def.section = sec;
1957 }
1958 defined_local = true;
1959 resolved_local = true;
1960 resolved_dynly = false;
1961 resolved_to_const = false;
1962 if (bfd_link_relocatable (info)
1963 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1964 rel->r_addend += sec->output_offset;
1965 }
1966 else
1967 {
1968 bool warned, ignored;
1969
1970 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1971 r_symndx, symtab_hdr, sym_hashes,
1972 h, sec, relocation,
1973 unresolved_reloc, warned, ignored);
1974 /* Here means symbol isn't local symbol only and 'h != NULL'. */
1975
1976 /* The 'unresolved_syms_in_objects' specify how to deal with undefined
1977 symbol. And 'dynamic_undefined_weak' specify what to do when
1978 meeting undefweak. */
1979
1980 if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
1981 {
1982 defined_local = false;
1983 resolved_local = false;
1984 resolved_to_const = (!is_dyn || h->dynindx == -1
1985 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
1986 resolved_dynly = !resolved_local && !resolved_to_const;
1987 }
1988 else if (warned)
1989 {
1990 /* Symbol undefined offen means failed already. I don't know why
1991 'warned' here but I guess it want to continue relocating as if
1992 no error occures to find other errors as more as possible. */
1993
1994 /* To avoid generating warning messages about truncated
1995 relocations, set the relocation's address to be the same as
1996 the start of this section. */
1997 relocation = (input_section->output_section
1998 ? input_section->output_section->vma
1999 : 0);
2000
2001 defined_local = relocation != 0;
2002 resolved_local = defined_local;
2003 resolved_to_const = !resolved_local;
2004 resolved_dynly = false;
2005 }
2006 else
2007 {
2008 defined_local = !unresolved_reloc && !ignored;
2009 resolved_local =
2010 defined_local && SYMBOL_REFERENCES_LOCAL (info, h);
2011 resolved_dynly = !resolved_local;
2012 resolved_to_const = !resolved_local && !resolved_dynly;
2013 }
2014 }
2015
2016 name = loongarch_sym_name (input_bfd, h, sym);
2017
2018 if (sec != NULL && discarded_section (sec))
2019 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
2020 1, relend, howto, 0, contents);
2021
2022 if (bfd_link_relocatable (info))
2023 continue;
2024
2025 /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2026 from removed linkonce sections, or sections discarded by a linker
2027 script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
2028 if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
2029 {
2030 defined_local = false;
2031 resolved_local = false;
2032 resolved_dynly = false;
2033 resolved_to_const = true;
2034 }
2035
2036 if (h && h->type == STT_GNU_IFUNC)
2037 {
2038 if (h->plt.offset == MINUS_ONE)
2039 info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against `%s':\n"
2040 "STT_GNU_IFUNC must have PLT stub"
2041 "\n",
2042 input_bfd, input_section,
2043 (bfd_vma) rel->r_offset, howto->name, name);
2044 defined_local = true;
2045 resolved_local = true;
2046 resolved_dynly = false;
2047 resolved_to_const = false;
2048 relocation = sec_addr (plt) + h->plt.offset;
2049 }
2050
2051 unresolved_reloc = resolved_dynly;
2052
2053 BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
2054
2055 BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));
2056
2057 BFD_ASSERT (!resolved_local || defined_local);
2058
2059 is_ie = false;
2060 switch (r_type)
2061 {
2062 case R_LARCH_MARK_PCREL:
2063 case R_LARCH_MARK_LA:
2064 case R_LARCH_NONE:
2065 r = bfd_reloc_continue;
2066 unresolved_reloc = false;
2067 break;
2068
2069 case R_LARCH_32:
2070 case R_LARCH_64:
2071 if (resolved_dynly || (is_pic && resolved_local))
2072 {
2073 Elf_Internal_Rela outrel;
2074
2075 /* When generating a shared object, these relocations are copied
2076 into the output file to be resolved at run time. */
2077
2078 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2079 input_section,
2080 rel->r_offset);
2081
2082 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2083 && (input_section->flags & SEC_ALLOC));
2084
2085 outrel.r_offset += sec_addr (input_section);
2086 if (resolved_dynly)
2087 {
2088 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2089 outrel.r_addend = rel->r_addend;
2090 }
2091 else
2092 {
2093 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2094 outrel.r_addend = relocation + rel->r_addend;
2095 }
2096
2097 if (unresolved_reloc)
2098 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2099 }
2100
2101 relocation += rel->r_addend;
2102 break;
2103
2104 case R_LARCH_ADD8:
2105 case R_LARCH_ADD16:
2106 case R_LARCH_ADD24:
2107 case R_LARCH_ADD32:
2108 case R_LARCH_ADD64:
2109 case R_LARCH_SUB8:
2110 case R_LARCH_SUB16:
2111 case R_LARCH_SUB24:
2112 case R_LARCH_SUB32:
2113 case R_LARCH_SUB64:
2114 if (resolved_dynly)
2115 fatal = (loongarch_reloc_is_fatal
2116 (info, input_bfd, input_section, rel, howto,
2117 bfd_reloc_undefined, is_undefweak, name,
2118 "Can't be resolved dynamically. "
2119 "If this procedure is hand-written assembly,\n"
2120 "there must be something like '.dword sym1 - sym2' "
2121 "to generate these relocs\n"
2122 "and we can't get known link-time address of "
2123 "these symbols."));
2124 else
2125 relocation += rel->r_addend;
2126 break;
2127
2128 case R_LARCH_TLS_DTPREL32:
2129 case R_LARCH_TLS_DTPREL64:
2130 if (resolved_dynly)
2131 {
2132 Elf_Internal_Rela outrel;
2133
2134 outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
2135 input_section,
2136 rel->r_offset);
2137 unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
2138 && (input_section->flags & SEC_ALLOC));
2139 outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
2140 outrel.r_offset += sec_addr (input_section);
2141 outrel.r_addend = rel->r_addend;
2142 if (unresolved_reloc)
2143 loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
2144 break;
2145 }
2146
2147 if (resolved_to_const)
2148 fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
2149 rel, howto,
2150 bfd_reloc_notsupported,
2151 is_undefweak, name,
2152 "Internal:");
2153 break;
2154
2155 case R_LARCH_SOP_PUSH_TLS_TPREL:
2156 if (resolved_local)
2157 {
2158 if (!elf_hash_table (info)->tls_sec)
2159 fatal = (loongarch_reloc_is_fatal
2160 (info, input_bfd, input_section, rel, howto,
2161 bfd_reloc_notsupported, is_undefweak, name,
2162 "TLS section not be created"));
2163 else
2164 relocation -= elf_hash_table (info)->tls_sec->vma;
2165 }
2166 else
2167 fatal = (loongarch_reloc_is_fatal
2168 (info, input_bfd, input_section, rel, howto,
2169 bfd_reloc_undefined, is_undefweak, name,
2170 "TLS LE just can be resolved local only."));
2171 break;
2172
2173 case R_LARCH_SOP_PUSH_ABSOLUTE:
2174 if (is_undefweak)
2175 {
2176 if (resolved_dynly)
2177 fatal = (loongarch_reloc_is_fatal
2178 (info, input_bfd, input_section, rel, howto,
2179 bfd_reloc_dangerous, is_undefweak, name,
2180 "Someone require us to resolve undefweak "
2181 "symbol dynamically. \n"
2182 "But this reloc can't be done. "
2183 "I think I can't throw error "
2184 "for this\n"
2185 "so I resolved it to 0. "
2186 "I suggest to re-compile with '-fpic'."));
2187
2188 relocation = 0;
2189 unresolved_reloc = false;
2190 break;
2191 }
2192
2193 if (resolved_to_const)
2194 {
2195 relocation += rel->r_addend;
2196 break;
2197 }
2198
2199 if (is_pic)
2200 {
2201 fatal = (loongarch_reloc_is_fatal
2202 (info, input_bfd, input_section, rel, howto,
2203 bfd_reloc_notsupported, is_undefweak, name,
2204 "Under PIC we don't know load address. Re-compile "
2205 "with '-fpic'?"));
2206 break;
2207 }
2208
2209 if (resolved_dynly)
2210 {
2211 if (!(plt && h && h->plt.offset != MINUS_ONE))
2212 {
2213 fatal = (loongarch_reloc_is_fatal
2214 (info, input_bfd, input_section, rel, howto,
2215 bfd_reloc_undefined, is_undefweak, name,
2216 "Can't be resolved dynamically. Try to re-compile "
2217 "with '-fpic'?"));
2218 break;
2219 }
2220
2221 if (rel->r_addend != 0)
2222 {
2223 fatal = (loongarch_reloc_is_fatal
2224 (info, input_bfd, input_section, rel, howto,
2225 bfd_reloc_notsupported, is_undefweak, name,
2226 "Shouldn't be with r_addend."));
2227 break;
2228 }
2229
2230 relocation = sec_addr (plt) + h->plt.offset;
2231 unresolved_reloc = false;
2232 break;
2233 }
2234
2235 if (resolved_local)
2236 {
2237 relocation += rel->r_addend;
2238 break;
2239 }
2240
2241 break;
2242
2243 case R_LARCH_SOP_PUSH_PCREL:
2244 case R_LARCH_SOP_PUSH_PLT_PCREL:
2245 unresolved_reloc = false;
2246
2247 if (resolved_to_const)
2248 {
2249 relocation += rel->r_addend;
2250 break;
2251 }
2252 else if (is_undefweak)
2253 {
2254 i = 0, j = 0;
2255 relocation = 0;
2256 if (resolved_dynly)
2257 {
2258 if (h && h->plt.offset != MINUS_ONE)
2259 i = 1, j = 2;
2260 else
2261 fatal = (loongarch_reloc_is_fatal
2262 (info, input_bfd, input_section, rel, howto,
2263 bfd_reloc_dangerous, is_undefweak, name,
2264 "Undefweak need to be resolved dynamically, "
2265 "but PLT stub doesn't represent."));
2266 }
2267 }
2268 else
2269 {
2270 if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
2271 {
2272 fatal = (loongarch_reloc_is_fatal
2273 (info, input_bfd, input_section, rel, howto,
2274 bfd_reloc_undefined, is_undefweak, name,
2275 "PLT stub does not represent and "
2276 "symbol not defined."));
2277 break;
2278 }
2279
2280 if (resolved_local)
2281 i = 0, j = 2;
2282 else /* if (resolved_dynly) */
2283 {
2284 if (!(h && h->plt.offset != MINUS_ONE))
2285 fatal = (loongarch_reloc_is_fatal
2286 (info, input_bfd, input_section, rel, howto,
2287 bfd_reloc_dangerous, is_undefweak, name,
2288 "Internal: PLT stub doesn't represent. "
2289 "Resolve it with pcrel"));
2290 i = 1, j = 3;
2291 }
2292 }
2293
2294 for (; i < j; i++)
2295 {
2296 if ((i & 1) == 0 && defined_local)
2297 {
2298 relocation -= pc;
2299 relocation += rel->r_addend;
2300 break;
2301 }
2302
2303 if ((i & 1) && h && h->plt.offset != MINUS_ONE)
2304 {
2305 if (rel->r_addend != 0)
2306 {
2307 fatal = (loongarch_reloc_is_fatal
2308 (info, input_bfd, input_section, rel, howto,
2309 bfd_reloc_notsupported, is_undefweak, name,
2310 "PLT shouldn't be with r_addend."));
2311 break;
2312 }
2313 relocation = sec_addr (plt) + h->plt.offset - pc;
2314 break;
2315 }
2316 }
2317 break;
2318
2319 case R_LARCH_SOP_PUSH_GPREL:
2320 unresolved_reloc = false;
2321
2322 if (rel->r_addend != 0)
2323 {
2324 fatal = (loongarch_reloc_is_fatal
2325 (info, input_bfd, input_section, rel, howto,
2326 bfd_reloc_notsupported, is_undefweak, name,
2327 "Shouldn't be with r_addend."));
2328 break;
2329 }
2330
2331 if (h != NULL)
2332 {
2333 off = h->got.offset;
2334
2335 if (off == MINUS_ONE)
2336 {
2337 fatal = (loongarch_reloc_is_fatal
2338 (info, input_bfd, input_section, rel, howto,
2339 bfd_reloc_notsupported, is_undefweak, name,
2340 "Internal: GOT entry doesn't represent."));
2341 break;
2342 }
2343
2344 if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h)
2345 || (is_pic && SYMBOL_REFERENCES_LOCAL (info, h)))
2346 {
2347 /* This is actually a static link, or it is a
2348 -Bsymbolic link and the symbol is defined
2349 locally, or the symbol was forced to be local
2350 because of a version file. We must initialize
2351 this entry in the global offset table. Since the
2352 offset must always be a multiple of the word size,
2353 we use the least significant bit to record whether
2354 we have initialized it already.
2355
2356 When doing a dynamic link, we create a .rela.got
2357 relocation entry to initialize the value. This
2358 is done in the finish_dynamic_symbol routine. */
2359
2360 if (resolved_dynly)
2361 {
2362 fatal = (loongarch_reloc_is_fatal
2363 (info, input_bfd, input_section, rel, howto,
2364 bfd_reloc_dangerous, is_undefweak, name,
2365 "Internal: here shouldn't dynamic."));
2366 }
2367
2368 if (!(defined_local || resolved_to_const))
2369 {
2370 fatal = (loongarch_reloc_is_fatal
2371 (info, input_bfd, input_section, rel, howto,
2372 bfd_reloc_undefined, is_undefweak, name,
2373 "Internal: "));
2374 break;
2375 }
2376
2377 if ((off & 1) != 0)
2378 off &= ~1;
2379 else
2380 {
2381 bfd_put_NN (output_bfd, relocation, got->contents + off);
2382 h->got.offset |= 1;
2383 }
2384 }
2385 }
2386 else
2387 {
2388 if (!local_got_offsets)
2389 {
2390 fatal = (loongarch_reloc_is_fatal
2391 (info, input_bfd, input_section, rel, howto,
2392 bfd_reloc_notsupported, is_undefweak, name,
2393 "Internal: local got offsets not reporesent."));
2394 break;
2395 }
2396
2397 off = local_got_offsets[r_symndx];
2398
2399 if (off == MINUS_ONE)
2400 {
2401 fatal = (loongarch_reloc_is_fatal
2402 (info, input_bfd, input_section, rel, howto,
2403 bfd_reloc_notsupported, is_undefweak, name,
2404 "Internal: GOT entry doesn't represent."));
2405 break;
2406 }
2407
2408 /* The offset must always be a multiple of the word size.
2409 So, we can use the least significant bit to record
2410 whether we have already processed this entry. */
2411 if ((off & 1) != 0)
2412 off &= ~1;
2413 else
2414 {
2415 if (is_pic)
2416 {
2417 asection *s;
2418 Elf_Internal_Rela outrel;
2419 /* We need to generate a R_LARCH_RELATIVE reloc
2420 for the dynamic linker. */
2421 s = htab->elf.srelgot;
2422 if (!s)
2423 {
2424 fatal = (loongarch_reloc_is_fatal
2425 (info, input_bfd, input_section, rel, howto,
2426 bfd_reloc_notsupported, is_undefweak, name,
2427 "Internal: '.rel.got' not represent"));
2428 break;
2429 }
2430
2431 outrel.r_offset = sec_addr (got) + off;
2432 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2433 outrel.r_addend = relocation; /* Link-time addr. */
2434 loongarch_elf_append_rela (output_bfd, s, &outrel);
2435 }
2436
2437 bfd_put_NN (output_bfd, relocation, got->contents + off);
2438 local_got_offsets[r_symndx] |= 1;
2439 }
2440 }
2441 relocation = off;
2442 break;
2443
2444 case R_LARCH_SOP_PUSH_TLS_GOT:
2445 case R_LARCH_SOP_PUSH_TLS_GD:
2446 if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
2447 is_ie = true;
2448 unresolved_reloc = false;
2449
2450 if (rel->r_addend != 0)
2451 {
2452 fatal = (loongarch_reloc_is_fatal
2453 (info, input_bfd, input_section, rel, howto,
2454 bfd_reloc_notsupported, is_undefweak, name,
2455 "Shouldn't be with r_addend."));
2456 break;
2457 }
2458
2459
2460 if (resolved_to_const && is_undefweak && h->dynindx != -1)
2461 {
2462 /* What if undefweak? Let rtld make a decision. */
2463 resolved_to_const = resolved_local = false;
2464 resolved_dynly = true;
2465 }
2466
2467 if (resolved_to_const)
2468 {
2469 fatal = (loongarch_reloc_is_fatal
2470 (info, input_bfd, input_section, rel, howto,
2471 bfd_reloc_notsupported, is_undefweak, name,
2472 "Internal: Shouldn't be resolved to const."));
2473 break;
2474 }
2475
2476 if (h != NULL)
2477 {
2478 off = h->got.offset;
2479 h->got.offset |= 1;
2480 }
2481 else
2482 {
2483 off = local_got_offsets[r_symndx];
2484 local_got_offsets[r_symndx] |= 1;
2485 }
2486
2487 if (off == MINUS_ONE)
2488 {
2489 fatal = (loongarch_reloc_is_fatal
2490 (info, input_bfd, input_section, rel, howto,
2491 bfd_reloc_notsupported, is_undefweak, name,
2492 "Internal: TLS GOT entry doesn't represent."));
2493 break;
2494 }
2495
2496 tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
2497
2498 /* If this symbol is referenced by both GD and IE TLS, the IE
2499 reference's GOT slot follows the GD reference's slots. */
2500 ie_off = 0;
2501 if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
2502 ie_off = 2 * GOT_ENTRY_SIZE;
2503
2504 if ((off & 1) != 0)
2505 off &= ~1;
2506 else
2507 {
2508 bfd_vma tls_block_off = 0;
2509 Elf_Internal_Rela outrel;
2510
2511 if (resolved_local)
2512 {
2513 if (!elf_hash_table (info)->tls_sec)
2514 {
2515 fatal = (loongarch_reloc_is_fatal
2516 (info, input_bfd, input_section, rel, howto,
2517 bfd_reloc_notsupported, is_undefweak, name,
2518 "Internal: TLS sec not represent."));
2519 break;
2520 }
2521 tls_block_off =
2522 relocation - elf_hash_table (info)->tls_sec->vma;
2523 }
2524
2525 if (tls_type & GOT_TLS_GD)
2526 {
2527 outrel.r_offset = sec_addr (got) + off;
2528 outrel.r_addend = 0;
2529 bfd_put_NN (output_bfd, 0, got->contents + off);
2530 if (resolved_local && bfd_link_executable (info))
2531 bfd_put_NN (output_bfd, 1, got->contents + off);
2532 else if (resolved_local /* && !bfd_link_executable (info) */)
2533 {
2534 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
2535 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2536 &outrel);
2537 }
2538 else /* if (resolved_dynly) */
2539 {
2540 outrel.r_info =
2541 ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPMODNN);
2542 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2543 &outrel);
2544 }
2545
2546 outrel.r_offset += GOT_ENTRY_SIZE;
2547 bfd_put_NN (output_bfd, tls_block_off,
2548 got->contents + off + GOT_ENTRY_SIZE);
2549 if (resolved_local)
2550 /* DTPREL known. */;
2551 else /* if (resolved_dynly) */
2552 {
2553 outrel.r_info =
2554 ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPRELNN);
2555 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2556 &outrel);
2557 }
2558 }
2559
2560 if (tls_type & GOT_TLS_IE)
2561 {
2562 outrel.r_offset = sec_addr (got) + off + ie_off;
2563 bfd_put_NN (output_bfd, tls_block_off,
2564 got->contents + off + ie_off);
2565 if (resolved_local && bfd_link_executable (info))
2566 /* TPREL known. */;
2567 else if (resolved_local /* && !bfd_link_executable (info) */)
2568 {
2569 outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
2570 outrel.r_addend = tls_block_off;
2571 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2572 &outrel);
2573 }
2574 else /* if (resolved_dynly) */
2575 {
2576 outrel.r_info =
2577 ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN);
2578 outrel.r_addend = 0;
2579 loongarch_elf_append_rela (output_bfd, htab->elf.srelgot,
2580 &outrel);
2581 }
2582 }
2583 }
2584
2585 relocation = off + (is_ie ? ie_off : 0);
2586 break;
2587
2588 default:
2589 break;
2590 }
2591
2592 if (fatal)
2593 break;
2594
2595 do
2596 {
2597 /* 'unresolved_reloc' means we haven't done it yet.
2598 We need help of dynamic linker to fix this memory location up. */
2599 if (!unresolved_reloc)
2600 break;
2601
2602 if (_bfd_elf_section_offset (output_bfd, info, input_section,
2603 rel->r_offset) == MINUS_ONE)
2604 /* WHY? May because it's invalid so skip checking.
2605 But why dynamic reloc a invalid section? */
2606 break;
2607
2608 if (input_section->output_section->flags & SEC_DEBUGGING)
2609 {
2610 fatal = (loongarch_reloc_is_fatal
2611 (info, input_bfd, input_section, rel, howto,
2612 bfd_reloc_dangerous, is_undefweak, name,
2613 "Seems dynamic linker not process "
2614 "sections 'SEC_DEBUGGING'."));
2615 }
2616 if (!is_dyn)
2617 break;
2618
2619 if ((info->flags & DF_TEXTREL) == 0)
2620 if (input_section->output_section->flags & SEC_READONLY)
2621 info->flags |= DF_TEXTREL;
2622 }
2623 while (0);
2624
2625 if (fatal)
2626 break;
2627
2628 loongarch_record_one_reloc (input_bfd, input_section, r_type,
2629 rel->r_offset, sym, h, rel->r_addend);
2630
2631 if (r != bfd_reloc_continue)
2632 r = perform_relocation (rel, input_section, howto, relocation,
2633 input_bfd, contents);
2634
2635 switch (r)
2636 {
2637 case bfd_reloc_dangerous:
2638 case bfd_reloc_continue:
2639 case bfd_reloc_ok:
2640 continue;
2641
2642 case bfd_reloc_overflow:
2643 /* Overflow value can't be filled in. */
2644 loongarch_dump_reloc_record (info->callbacks->info);
2645 info->callbacks->reloc_overflow
2646 (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
2647 input_bfd, input_section, rel->r_offset);
2648 break;
2649
2650 case bfd_reloc_outofrange:
2651 /* Stack state incorrect. */
2652 loongarch_dump_reloc_record (info->callbacks->info);
2653 info->callbacks->info
2654 ("%X%H: Internal stack state is incorrect.\n"
2655 "Want to push to full stack or pop from empty stack?\n",
2656 input_bfd, input_section, rel->r_offset);
2657 break;
2658
2659 case bfd_reloc_notsupported:
2660 info->callbacks->info ("%X%H: Unknown relocation type.\n", input_bfd,
2661 input_section, rel->r_offset);
2662 break;
2663
2664 default:
2665 info->callbacks->info ("%X%H: Internal: unknown error.\n", input_bfd,
2666 input_section, rel->r_offset);
2667 break;
2668 }
2669
2670 fatal = true;
2671 break;
2672 }
2673
2674 return !fatal;
2675 }
2676
2677 /* Finish up dynamic symbol handling. We set the contents of various
2678 dynamic sections here. */
2679
2680 static bool
2681 loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
2682 struct bfd_link_info *info,
2683 struct elf_link_hash_entry *h,
2684 Elf_Internal_Sym *sym)
2685 {
2686 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2687 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
2688 asection *plt = NULL;
2689
2690 if (h->plt.offset != MINUS_ONE)
2691 {
2692 size_t i, plt_idx;
2693 asection *gotplt, *relplt;
2694 bfd_vma got_address;
2695 uint32_t plt_entry[PLT_ENTRY_INSNS];
2696 bfd_byte *loc;
2697 Elf_Internal_Rela rela;
2698
2699 plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
2700
2701 /* One of '.plt' and '.iplt' represents. */
2702 BFD_ASSERT (!!htab->elf.splt ^ !!htab->elf.iplt);
2703
2704 if (htab->elf.splt)
2705 {
2706 BFD_ASSERT ((h->type == STT_GNU_IFUNC
2707 && SYMBOL_REFERENCES_LOCAL (info, h))
2708 || h->dynindx != -1);
2709
2710 plt = htab->elf.splt;
2711 gotplt = htab->elf.sgotplt;
2712 relplt = htab->elf.srelplt;
2713 got_address =
2714 sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
2715 }
2716 else /* if (htab->elf.iplt) */
2717 {
2718 BFD_ASSERT (h->type == STT_GNU_IFUNC
2719 && SYMBOL_REFERENCES_LOCAL (info, h));
2720
2721 plt = htab->elf.iplt;
2722 gotplt = htab->elf.igotplt;
2723 relplt = htab->elf.irelplt;
2724 got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
2725 }
2726
2727 /* Find out where the .plt entry should go. */
2728 loc = plt->contents + h->plt.offset;
2729
2730 /* Fill in the PLT entry itself. */
2731 if (!loongarch_make_plt_entry (got_address,
2732 sec_addr (plt) + h->plt.offset,
2733 plt_entry))
2734 return false;
2735
2736 for (i = 0; i < PLT_ENTRY_INSNS; i++)
2737 bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
2738
2739 /* Fill in the initial value of the .got.plt entry. */
2740 loc = gotplt->contents + (got_address - sec_addr (gotplt));
2741 bfd_put_NN (output_bfd, sec_addr (plt), loc);
2742
2743 rela.r_offset = got_address;
2744 if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
2745 {
2746 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2747 rela.r_addend = (h->root.u.def.value
2748 + h->root.u.def.section->output_section->vma
2749 + h->root.u.def.section->output_offset);
2750 }
2751 else
2752 {
2753 /* Fill in the entry in the .rela.plt section. */
2754 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
2755 rela.r_addend = 0;
2756 }
2757
2758 loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
2759 bed->s->swap_reloca_out (output_bfd, &rela, loc);
2760
2761 if (!h->def_regular)
2762 {
2763 /* Mark the symbol as undefined, rather than as defined in
2764 the .plt section. Leave the value alone. */
2765 sym->st_shndx = SHN_UNDEF;
2766 /* If the symbol is weak, we do need to clear the value.
2767 Otherwise, the PLT entry would provide a definition for
2768 the symbol even if the symbol wasn't defined anywhere,
2769 and so the symbol would never be NULL. */
2770 if (!h->ref_regular_nonweak)
2771 sym->st_value = 0;
2772 }
2773 }
2774
2775 if (h->got.offset != MINUS_ONE
2776 /* TLS got entry have been handled in elf_relocate_section. */
2777 && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
2778 /* have allocated got entry but not allocated rela before. */
2779 && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
2780 {
2781 asection *sgot, *srela;
2782 Elf_Internal_Rela rela;
2783 bfd_vma off = h->got.offset & ~(bfd_vma) 1;
2784
2785 /* This symbol has an entry in the GOT. Set it up. */
2786
2787 sgot = htab->elf.sgot;
2788 srela = htab->elf.srelgot;
2789 BFD_ASSERT (sgot && srela);
2790
2791 rela.r_offset = sec_addr (sgot) + off;
2792
2793 if (h->type == STT_GNU_IFUNC)
2794 {
2795 if (elf_hash_table (info)->dynamic_sections_created
2796 && SYMBOL_REFERENCES_LOCAL (info, h))
2797 {
2798 asection *sec = h->root.u.def.section;
2799 rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
2800 rela.r_addend = (h->root.u.def.value + sec->output_section->vma
2801 + sec->output_offset);
2802 bfd_put_NN (output_bfd, 0, sgot->contents + off);
2803 }
2804 else
2805 {
2806 BFD_ASSERT (plt);
2807 rela.r_info
2808 = ELFNN_R_INFO (0, (bfd_link_pic (info)
2809 ? R_LARCH_RELATIVE : R_LARCH_NONE));
2810 rela.r_addend =
2811 plt->output_section->vma + plt->output_offset + h->plt.offset;
2812 bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
2813 }
2814 }
2815 else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
2816 {
2817 BFD_ASSERT (h->got.offset & 1 /* Has been filled in addr. */);
2818 asection *sec = h->root.u.def.section;
2819 rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
2820 rela.r_addend = (h->root.u.def.value + sec->output_section->vma
2821 + sec->output_offset);
2822 }
2823 else
2824 {
2825 BFD_ASSERT ((h->got.offset & 1) == 0);
2826 BFD_ASSERT (h->dynindx != -1);
2827 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
2828 rela.r_addend = 0;
2829 }
2830
2831 loongarch_elf_append_rela (output_bfd, srela, &rela);
2832 }
2833
2834 if (h->needs_copy)
2835 {
2836 Elf_Internal_Rela rela;
2837 asection *s;
2838
2839 /* This symbols needs a copy reloc. Set it up. */
2840 BFD_ASSERT (h->dynindx != -1);
2841
2842 rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value;
2843 rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY);
2844 rela.r_addend = 0;
2845 if (h->root.u.def.section == htab->elf.sdynrelro)
2846 s = htab->elf.sreldynrelro;
2847 else
2848 s = htab->elf.srelbss;
2849 loongarch_elf_append_rela (output_bfd, s, &rela);
2850 }
2851
2852 /* Mark some specially defined symbols as absolute. */
2853 if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
2854 sym->st_shndx = SHN_ABS;
2855
2856 return true;
2857 }
2858
2859 /* Finish up the dynamic sections. */
2860
2861 static bool
2862 loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
2863 asection *sdyn)
2864 {
2865 struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
2866 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
2867 size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
2868 bfd_byte *dyncon, *dynconend;
2869
2870 dynconend = sdyn->contents + sdyn->size;
2871 for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
2872 {
2873 Elf_Internal_Dyn dyn;
2874 asection *s;
2875 int skipped = 0;
2876
2877 bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
2878
2879 switch (dyn.d_tag)
2880 {
2881 case DT_PLTGOT:
2882 s = htab->elf.sgotplt;
2883 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
2884 break;
2885 case DT_JMPREL:
2886 s = htab->elf.srelplt;
2887 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
2888 break;
2889 case DT_PLTRELSZ:
2890 s = htab->elf.srelplt;
2891 dyn.d_un.d_val = s->size;
2892 break;
2893 case DT_TEXTREL:
2894 if ((info->flags & DF_TEXTREL) == 0)
2895 skipped = 1;
2896 break;
2897 case DT_FLAGS:
2898 if ((info->flags & DF_TEXTREL) == 0)
2899 dyn.d_un.d_val &= ~DF_TEXTREL;
2900 break;
2901 }
2902 if (skipped)
2903 skipped_size += dynsize;
2904 else
2905 bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
2906 }
2907 /* Wipe out any trailing entries if we shifted down a dynamic tag. */
2908 memset (dyncon - skipped_size, 0, skipped_size);
2909 return true;
2910 }
2911
2912 /* Finish up local dynamic symbol handling. We set the contents of
2913 various dynamic sections here. */
2914
2915 static bool
2916 elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
2917 {
2918 struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
2919 struct bfd_link_info *info = (struct bfd_link_info *) inf;
2920
2921 return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
2922 }
2923
2924 static bool
2925 loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
2926 struct bfd_link_info *info)
2927 {
2928 bfd *dynobj;
2929 asection *sdyn, *plt, *gotplt = NULL;
2930 struct loongarch_elf_link_hash_table *htab;
2931
2932 htab = loongarch_elf_hash_table (info);
2933 BFD_ASSERT (htab);
2934 dynobj = htab->elf.dynobj;
2935 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
2936
2937 if (elf_hash_table (info)->dynamic_sections_created)
2938 {
2939 BFD_ASSERT (htab->elf.splt && sdyn);
2940
2941 if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
2942 return false;
2943 }
2944
2945 if ((plt = htab->elf.splt))
2946 gotplt = htab->elf.sgotplt;
2947 else if ((plt = htab->elf.iplt))
2948 gotplt = htab->elf.igotplt;
2949
2950 if (plt && 0 < plt->size)
2951 {
2952 size_t i;
2953 uint32_t plt_header[PLT_HEADER_INSNS];
2954 if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
2955 plt_header))
2956 return false;
2957
2958 for (i = 0; i < PLT_HEADER_INSNS; i++)
2959 bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
2960
2961 elf_section_data (plt->output_section)->this_hdr.sh_entsize =
2962 PLT_ENTRY_SIZE;
2963 }
2964
2965 if (htab->elf.sgotplt)
2966 {
2967 asection *output_section = htab->elf.sgotplt->output_section;
2968
2969 if (bfd_is_abs_section (output_section))
2970 {
2971 _bfd_error_handler (_("discarded output section: `%pA'"),
2972 htab->elf.sgotplt);
2973 return false;
2974 }
2975
2976 if (0 < htab->elf.sgotplt->size)
2977 {
2978 /* Write the first two entries in .got.plt, needed for the dynamic
2979 linker. */
2980 bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
2981
2982 bfd_put_NN (output_bfd, (bfd_vma) 0,
2983 htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
2984 }
2985
2986 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
2987 }
2988
2989 if (htab->elf.sgot)
2990 {
2991 asection *output_section = htab->elf.sgot->output_section;
2992
2993 if (0 < htab->elf.sgot->size)
2994 {
2995 /* Set the first entry in the global offset table to the address of
2996 the dynamic section. */
2997 bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
2998 bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
2999 }
3000
3001 elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
3002 }
3003
3004 /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
3005 htab_traverse (htab->loc_hash_table,
3006 (void *) elfNN_loongarch_finish_local_dynamic_symbol, info);
3007
3008 return true;
3009 }
3010
3011 /* Return address for Ith PLT stub in section PLT, for relocation REL
3012 or (bfd_vma) -1 if it should not be included. */
3013
3014 static bfd_vma
3015 loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
3016 const arelent *rel ATTRIBUTE_UNUSED)
3017 {
3018 return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
3019 }
3020
3021 static enum elf_reloc_type_class
3022 loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
3023 const asection *rel_sec ATTRIBUTE_UNUSED,
3024 const Elf_Internal_Rela *rela)
3025 {
3026 struct loongarch_elf_link_hash_table *htab;
3027 htab = loongarch_elf_hash_table (info);
3028
3029 if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
3030 {
3031 /* Check relocation against STT_GNU_IFUNC symbol if there are
3032 dynamic symbols. */
3033 bfd *abfd = info->output_bfd;
3034 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
3035 unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
3036 if (r_symndx != STN_UNDEF)
3037 {
3038 Elf_Internal_Sym sym;
3039 if (!bed->s->swap_symbol_in (abfd,
3040 htab->elf.dynsym->contents
3041 + r_symndx * bed->s->sizeof_sym,
3042 0, &sym))
3043 {
3044 /* xgettext:c-format */
3045 _bfd_error_handler (_("%pB symbol number %lu references"
3046 " nonexistent SHT_SYMTAB_SHNDX section"),
3047 abfd, r_symndx);
3048 /* Ideally an error class should be returned here. */
3049 }
3050 else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
3051 return reloc_class_ifunc;
3052 }
3053 }
3054
3055 switch (ELFNN_R_TYPE (rela->r_info))
3056 {
3057 case R_LARCH_IRELATIVE:
3058 return reloc_class_ifunc;
3059 case R_LARCH_RELATIVE:
3060 return reloc_class_relative;
3061 case R_LARCH_JUMP_SLOT:
3062 return reloc_class_plt;
3063 case R_LARCH_COPY:
3064 return reloc_class_copy;
3065 default:
3066 return reloc_class_normal;
3067 }
3068 }
3069
3070 /* Copy the extra info we tack onto an elf_link_hash_entry. */
3071
3072 static void
3073 loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
3074 struct elf_link_hash_entry *dir,
3075 struct elf_link_hash_entry *ind)
3076 {
3077 struct loongarch_elf_link_hash_entry *edir, *eind;
3078
3079 edir = (struct loongarch_elf_link_hash_entry *) dir;
3080 eind = (struct loongarch_elf_link_hash_entry *) ind;
3081
3082 if (eind->dyn_relocs != NULL)
3083 {
3084 if (edir->dyn_relocs != NULL)
3085 {
3086 struct elf_dyn_relocs **pp;
3087 struct elf_dyn_relocs *p;
3088
3089 /* Add reloc counts against the indirect sym to the direct sym
3090 list. Merge any entries against the same section. */
3091 for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
3092 {
3093 struct elf_dyn_relocs *q;
3094
3095 for (q = edir->dyn_relocs; q != NULL; q = q->next)
3096 if (q->sec == p->sec)
3097 {
3098 q->pc_count += p->pc_count;
3099 q->count += p->count;
3100 *pp = p->next;
3101 break;
3102 }
3103 if (q == NULL)
3104 pp = &p->next;
3105 }
3106 *pp = edir->dyn_relocs;
3107 }
3108
3109 edir->dyn_relocs = eind->dyn_relocs;
3110 eind->dyn_relocs = NULL;
3111 }
3112
3113 if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
3114 {
3115 edir->tls_type = eind->tls_type;
3116 eind->tls_type = GOT_UNKNOWN;
3117 }
3118 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3119 }
3120
3121 #define PRSTATUS_SIZE 0x1d8
3122 #define PRSTATUS_OFFSET_PR_CURSIG 0xc
3123 #define PRSTATUS_OFFSET_PR_PID 0x20
3124 #define ELF_GREGSET_T_SIZE 0x168
3125 #define PRSTATUS_OFFSET_PR_REG 0x70
3126
3127 /* Support for core dump NOTE sections. */
3128
3129 static bool
3130 loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
3131 {
3132 switch (note->descsz)
3133 {
3134 default:
3135 return false;
3136
3137 /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
3138 case PRSTATUS_SIZE:
3139 /* pr_cursig */
3140 elf_tdata (abfd)->core->signal =
3141 bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
3142
3143 /* pr_pid */
3144 elf_tdata (abfd)->core->lwpid =
3145 bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
3146 break;
3147 }
3148
3149 /* Make a ".reg/999" section. */
3150 return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
3151 note->descpos
3152 + PRSTATUS_OFFSET_PR_REG);
3153 }
3154
3155 #define PRPSINFO_SIZE 0x88
3156 #define PRPSINFO_OFFSET_PR_PID 0x18
3157 #define PRPSINFO_OFFSET_PR_FNAME 0x28
3158 #define PRPSINFO_SIZEOF_PR_FNAME 0x10
3159 #define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
3160 #define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
3161
3162
3163 static bool
3164 loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
3165 {
3166 switch (note->descsz)
3167 {
3168 default:
3169 return false;
3170
3171 /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
3172 case PRPSINFO_SIZE:
3173 /* pr_pid */
3174 elf_tdata (abfd)->core->pid =
3175 bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
3176
3177 /* pr_fname */
3178 elf_tdata (abfd)->core->program =
3179 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
3180 PRPSINFO_SIZEOF_PR_FNAME);
3181
3182 /* pr_psargs */
3183 elf_tdata (abfd)->core->command =
3184 _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
3185 PRPSINFO_SIZEOF_PR_PS_ARGS);
3186 break;
3187 }
3188
3189 /* Note that for some reason, a spurious space is tacked
3190 onto the end of the args in some (at least one anyway)
3191 implementations, so strip it off if it exists. */
3192
3193 {
3194 char *command = elf_tdata (abfd)->core->command;
3195 int n = strlen (command);
3196
3197 if (0 < n && command[n - 1] == ' ')
3198 command[n - 1] = '\0';
3199 }
3200
3201 return true;
3202 }
3203
3204 /* Set the right mach type. */
3205 static bool
3206 loongarch_elf_object_p (bfd *abfd)
3207 {
3208 /* There are only two mach types in LoongArch currently. */
3209 if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
3210 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
3211 else
3212 bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
3213 return true;
3214 }
3215
3216 static asection *
3217 loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
3218 Elf_Internal_Rela *rel,
3219 struct elf_link_hash_entry *h,
3220 Elf_Internal_Sym *sym)
3221 {
3222 if (h != NULL)
3223 switch (ELFNN_R_TYPE (rel->r_info))
3224 {
3225 case R_LARCH_GNU_VTINHERIT:
3226 case R_LARCH_GNU_VTENTRY:
3227 return NULL;
3228 }
3229
3230 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
3231 }
3232
3233 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
3234 #define TARGET_LITTLE_NAME "elfNN-loongarch"
3235 #define ELF_ARCH bfd_arch_loongarch
3236 #define ELF_TARGET_ID LARCH_ELF_DATA
3237 #define ELF_MACHINE_CODE EM_LOONGARCH
3238 #define ELF_MAXPAGESIZE 0x4000
3239 #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
3240 #define bfd_elfNN_bfd_link_hash_table_create \
3241 loongarch_elf_link_hash_table_create
3242 #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
3243 #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
3244 #define elf_info_to_howto loongarch_info_to_howto_rela
3245 #define bfd_elfNN_bfd_merge_private_bfd_data \
3246 elfNN_loongarch_merge_private_bfd_data
3247
3248 #define elf_backend_reloc_type_class loongarch_reloc_type_class
3249 #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
3250 #define elf_backend_create_dynamic_sections \
3251 loongarch_elf_create_dynamic_sections
3252 #define elf_backend_check_relocs loongarch_elf_check_relocs
3253 #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
3254 #define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
3255 #define elf_backend_relocate_section loongarch_elf_relocate_section
3256 #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
3257 #define elf_backend_finish_dynamic_sections \
3258 loongarch_elf_finish_dynamic_sections
3259 #define elf_backend_object_p loongarch_elf_object_p
3260 #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
3261 #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
3262 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
3263 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
3264
3265 #include "elfNN-target.h"