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