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