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