Home | History | Annotate | Line # | Download | only in bfd
      1      1.1  christos /* LoongArch-specific support for NN-bit ELF.
      2  1.1.1.3  christos    Copyright (C) 2021-2025 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.1.3  christos #include "splay-tree.h"
     29      1.1  christos #include "elf/loongarch.h"
     30      1.1  christos #include "elfxx-loongarch.h"
     31  1.1.1.2  christos #include "opcode/loongarch.h"
     32      1.1  christos 
     33      1.1  christos static bool
     34      1.1  christos loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
     35      1.1  christos 			      Elf_Internal_Rela *dst)
     36      1.1  christos {
     37      1.1  christos   cache_ptr->howto = loongarch_elf_rtype_to_howto (abfd,
     38      1.1  christos 						   ELFNN_R_TYPE (dst->r_info));
     39      1.1  christos   return cache_ptr->howto != NULL;
     40      1.1  christos }
     41      1.1  christos 
     42      1.1  christos /* LoongArch ELF linker hash entry.  */
     43      1.1  christos struct loongarch_elf_link_hash_entry
     44      1.1  christos {
     45      1.1  christos   struct elf_link_hash_entry elf;
     46      1.1  christos 
     47      1.1  christos #define GOT_UNKNOWN 0
     48      1.1  christos #define GOT_NORMAL  1
     49      1.1  christos #define GOT_TLS_GD  2
     50      1.1  christos #define GOT_TLS_IE  4
     51      1.1  christos #define GOT_TLS_LE  8
     52  1.1.1.2  christos #define GOT_TLS_GDESC 16
     53  1.1.1.2  christos 
     54  1.1.1.2  christos #define GOT_TLS_GD_BOTH_P(tls_type) \
     55  1.1.1.2  christos   ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
     56  1.1.1.2  christos #define GOT_TLS_GD_ANY_P(tls_type) \
     57  1.1.1.2  christos   ((tls_type & GOT_TLS_GD) || (tls_type & GOT_TLS_GDESC))
     58      1.1  christos   char tls_type;
     59      1.1  christos };
     60      1.1  christos 
     61      1.1  christos #define loongarch_elf_hash_entry(ent)	\
     62      1.1  christos   ((struct loongarch_elf_link_hash_entry *) (ent))
     63      1.1  christos 
     64      1.1  christos struct _bfd_loongarch_elf_obj_tdata
     65      1.1  christos {
     66      1.1  christos   struct elf_obj_tdata root;
     67      1.1  christos 
     68      1.1  christos   /* The tls_type for each local got entry.  */
     69      1.1  christos   char *local_got_tls_type;
     70      1.1  christos };
     71      1.1  christos 
     72      1.1  christos #define _bfd_loongarch_elf_tdata(abfd)	\
     73      1.1  christos   ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
     74      1.1  christos 
     75      1.1  christos #define _bfd_loongarch_elf_local_got_tls_type(abfd)	\
     76      1.1  christos   (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
     77      1.1  christos 
     78      1.1  christos #define _bfd_loongarch_elf_tls_type(abfd, h, symndx)			\
     79      1.1  christos   (*((h) != NULL							\
     80      1.1  christos      ? &loongarch_elf_hash_entry (h)->tls_type				\
     81      1.1  christos      : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
     82      1.1  christos 
     83      1.1  christos #define is_loongarch_elf(bfd)						\
     84      1.1  christos   (bfd_get_flavour (bfd) == bfd_target_elf_flavour			\
     85      1.1  christos    && elf_tdata (bfd) != NULL						\
     86      1.1  christos    && elf_object_id (bfd) == LARCH_ELF_DATA)
     87      1.1  christos 
     88  1.1.1.3  christos static bool
     89  1.1.1.3  christos elfNN_loongarch_object (bfd *abfd)
     90  1.1.1.3  christos {
     91  1.1.1.3  christos   return bfd_elf_allocate_object (abfd,
     92  1.1.1.3  christos 				  sizeof (struct _bfd_loongarch_elf_obj_tdata));
     93  1.1.1.3  christos }
     94  1.1.1.3  christos 
     95  1.1.1.3  christos struct relr_entry
     96  1.1.1.3  christos {
     97  1.1.1.3  christos   asection *sec;
     98  1.1.1.3  christos   bfd_vma off;
     99  1.1.1.3  christos };
    100  1.1.1.3  christos 
    101      1.1  christos struct loongarch_elf_link_hash_table
    102      1.1  christos {
    103      1.1  christos   struct elf_link_hash_table elf;
    104      1.1  christos 
    105      1.1  christos   /* Short-cuts to get to dynamic linker sections.  */
    106      1.1  christos   asection *sdyntdata;
    107      1.1  christos 
    108      1.1  christos   /* Small local sym to section mapping cache.  */
    109      1.1  christos   struct sym_cache sym_cache;
    110      1.1  christos 
    111      1.1  christos   /* Used by local STT_GNU_IFUNC symbols.  */
    112      1.1  christos   htab_t loc_hash_table;
    113      1.1  christos   void *loc_hash_memory;
    114      1.1  christos 
    115      1.1  christos   /* The max alignment of output sections.  */
    116      1.1  christos   bfd_vma max_alignment;
    117  1.1.1.2  christos 
    118  1.1.1.2  christos   /* The data segment phase, don't relax the section
    119  1.1.1.2  christos      when it is exp_seg_relro_adjust.  */
    120  1.1.1.2  christos   int *data_segment_phase;
    121  1.1.1.3  christos 
    122  1.1.1.3  christos   /* Array of relative relocs to be emitted in DT_RELR format.  */
    123  1.1.1.3  christos   bfd_size_type relr_alloc;
    124  1.1.1.3  christos   bfd_size_type relr_count;
    125  1.1.1.3  christos   struct relr_entry *relr;
    126  1.1.1.3  christos 
    127  1.1.1.3  christos   /* Sorted output addresses of above relative relocs.  */
    128  1.1.1.3  christos   bfd_vma *relr_sorted;
    129  1.1.1.3  christos 
    130  1.1.1.3  christos   /* Layout recomputation count.  */
    131  1.1.1.3  christos   bfd_size_type relr_layout_iter;
    132  1.1.1.3  christos 
    133  1.1.1.3  christos   /* In BFD DT_RELR is implemented as a "relaxation."  If in a relax trip
    134  1.1.1.3  christos      size_relative_relocs is updating the layout, relax_section may see
    135  1.1.1.3  christos      a partially updated state (some sections have vma updated but the
    136  1.1.1.3  christos      others do not), and it's unsafe to do the normal relaxation.  */
    137  1.1.1.3  christos   bool layout_mutating_for_relr;
    138  1.1.1.3  christos 
    139  1.1.1.3  christos   /* Pending relaxation (byte deletion) operations meant for roughly
    140  1.1.1.3  christos      sequential access.  */
    141  1.1.1.3  christos   splay_tree pending_delete_ops;
    142  1.1.1.3  christos };
    143  1.1.1.3  christos 
    144  1.1.1.3  christos struct loongarch_elf_section_data
    145  1.1.1.3  christos {
    146  1.1.1.3  christos   struct bfd_elf_section_data elf;
    147  1.1.1.3  christos 
    148  1.1.1.3  christos   /* &htab->relr[i] where i is the smallest number s.t.
    149  1.1.1.3  christos      elf_section_data (htab->relr[i].sec) == &elf.
    150  1.1.1.3  christos      NULL if there exists no such i.  */
    151  1.1.1.3  christos   struct relr_entry *relr;
    152      1.1  christos };
    153      1.1  christos 
    154  1.1.1.3  christos /* We need an additional field in elf_section_data to handle complex
    155  1.1.1.3  christos    interactions between DT_RELR and relaxation.  */
    156  1.1.1.3  christos static bool
    157  1.1.1.3  christos loongarch_elf_new_section_hook (bfd *abfd, asection *sec)
    158  1.1.1.3  christos {
    159  1.1.1.3  christos   struct loongarch_elf_section_data *sdata;
    160  1.1.1.3  christos 
    161  1.1.1.3  christos   sdata = bfd_zalloc (abfd, sizeof (*sdata));
    162  1.1.1.3  christos   if (!sdata)
    163  1.1.1.3  christos     return false;
    164  1.1.1.3  christos   sec->used_by_bfd = sdata;
    165  1.1.1.3  christos 
    166  1.1.1.3  christos   return _bfd_elf_new_section_hook (abfd, sec);
    167  1.1.1.3  christos }
    168  1.1.1.3  christos 
    169  1.1.1.3  christos #define loongarch_elf_section_data(x) \
    170  1.1.1.3  christos   ((struct loongarch_elf_section_data *) elf_section_data (x))
    171  1.1.1.3  christos 
    172      1.1  christos /* Get the LoongArch ELF linker hash table from a link_info structure.  */
    173      1.1  christos #define loongarch_elf_hash_table(p)					\
    174  1.1.1.3  christos     ((struct loongarch_elf_link_hash_table *) ((p)->hash))		\
    175  1.1.1.3  christos 
    176  1.1.1.3  christos /* During linker relaxation, indicates whether the section has already
    177  1.1.1.3  christos    undergone alignment processing and no more byte deletion is permitted.  */
    178  1.1.1.3  christos #define loongarch_sec_closed_for_deletion(sec) ((sec)->sec_flg0)
    179      1.1  christos 
    180      1.1  christos #define MINUS_ONE ((bfd_vma) 0 - 1)
    181      1.1  christos 
    182      1.1  christos #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
    183      1.1  christos 
    184      1.1  christos #define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
    185      1.1  christos #define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
    186      1.1  christos 
    187      1.1  christos #define PLT_HEADER_INSNS 8
    188      1.1  christos #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
    189      1.1  christos 
    190      1.1  christos #define PLT_ENTRY_INSNS 4
    191      1.1  christos #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
    192      1.1  christos 
    193      1.1  christos #define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
    194      1.1  christos 
    195  1.1.1.3  christos /* Reserve two entries of GOTPLT for ld.so, one is used for PLT
    196  1.1.1.3  christos    resolver _dl_runtime_resolve, the other is used for link map.  */
    197      1.1  christos #define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
    198      1.1  christos 
    199      1.1  christos #define elf_backend_want_got_plt 1
    200      1.1  christos 
    201      1.1  christos #define elf_backend_plt_readonly 1
    202      1.1  christos 
    203  1.1.1.2  christos #define elf_backend_want_plt_sym 1
    204      1.1  christos #define elf_backend_plt_alignment 4
    205      1.1  christos #define elf_backend_can_gc_sections 1
    206  1.1.1.2  christos #define elf_backend_can_refcount 1
    207      1.1  christos #define elf_backend_want_got_sym 1
    208      1.1  christos 
    209      1.1  christos #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
    210      1.1  christos 
    211      1.1  christos #define elf_backend_want_dynrelro 1
    212  1.1.1.2  christos #define elf_backend_rela_normal 1
    213  1.1.1.2  christos #define elf_backend_default_execstack 0
    214  1.1.1.2  christos 
    215  1.1.1.2  christos #define IS_LOONGARCH_TLS_TRANS_RELOC(R_TYPE)  \
    216  1.1.1.2  christos   ((R_TYPE) == R_LARCH_TLS_DESC_PC_HI20	      \
    217  1.1.1.2  christos    || (R_TYPE) == R_LARCH_TLS_DESC_PC_LO12    \
    218  1.1.1.2  christos    || (R_TYPE) == R_LARCH_TLS_DESC_LD	      \
    219  1.1.1.2  christos    || (R_TYPE) == R_LARCH_TLS_DESC_CALL	      \
    220  1.1.1.2  christos    || (R_TYPE) == R_LARCH_TLS_IE_PC_HI20      \
    221  1.1.1.2  christos    || (R_TYPE) == R_LARCH_TLS_IE_PC_LO12)
    222      1.1  christos 
    223  1.1.1.3  christos #define IS_OUTDATED_TLS_LE_RELOC(R_TYPE)  \
    224  1.1.1.3  christos   ((R_TYPE) == R_LARCH_TLS_LE_HI20	  \
    225  1.1.1.3  christos    || (R_TYPE) == R_LARCH_TLS_LE_LO12	  \
    226  1.1.1.3  christos    || (R_TYPE) == R_LARCH_TLS_LE64_LO20	  \
    227  1.1.1.3  christos    || (R_TYPE) == R_LARCH_TLS_LE64_HI12)
    228  1.1.1.3  christos 
    229  1.1.1.3  christos #define IS_CALL_RELOC(R_TYPE)	  \
    230  1.1.1.3  christos   ((R_TYPE) == R_LARCH_B26	  \
    231  1.1.1.3  christos    ||(R_TYPE) == R_LARCH_CALL36)
    232  1.1.1.3  christos 
    233  1.1.1.3  christos /* If TLS GD/IE need dynamic relocations, INDX will be the dynamic indx,
    234  1.1.1.3  christos    and set NEED_RELOC to true used in allocate_dynrelocs and
    235  1.1.1.3  christos    loongarch_elf_relocate_section for TLS GD/IE.  */
    236  1.1.1.3  christos #define LARCH_TLS_GD_IE_NEED_DYN_RELOC(INFO, DYN, H, INDX, NEED_RELOC) \
    237  1.1.1.3  christos   do \
    238  1.1.1.3  christos     { \
    239  1.1.1.3  christos       if ((H) != NULL \
    240  1.1.1.3  christos 	  && (H)->dynindx != -1 \
    241  1.1.1.3  christos 	  && WILL_CALL_FINISH_DYNAMIC_SYMBOL ((DYN), \
    242  1.1.1.3  christos 				    bfd_link_pic (INFO), (H))) \
    243  1.1.1.3  christos       (INDX) = (H)->dynindx; \
    244  1.1.1.3  christos       if (((H) == NULL \
    245  1.1.1.3  christos 	    || ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT \
    246  1.1.1.3  christos 	    || (H)->root.type != bfd_link_hash_undefweak) \
    247  1.1.1.3  christos 	    && (!bfd_link_executable (INFO) \
    248  1.1.1.3  christos 	      || (INDX) != 0)) \
    249  1.1.1.3  christos       (NEED_RELOC) = true; \
    250  1.1.1.3  christos     } \
    251  1.1.1.3  christos     while (0)
    252  1.1.1.3  christos 
    253  1.1.1.3  christos /* TL;DR always use it in this file instead when you want to type
    254  1.1.1.3  christos    SYMBOL_REFERENCES_LOCAL.
    255  1.1.1.3  christos 
    256  1.1.1.3  christos    It's like SYMBOL_REFERENCES_LOCAL, but it returns true for local
    257  1.1.1.3  christos    protected functions.  It happens to be same as SYMBOL_CALLS_LOCAL but
    258  1.1.1.3  christos    let's not reuse SYMBOL_CALLS_LOCAL or "CALLS" may puzzle people.
    259  1.1.1.3  christos 
    260  1.1.1.3  christos    We do generate a PLT entry when someone attempts to la.pcrel an external
    261  1.1.1.3  christos    function.  But we never really implemented "R_LARCH_COPY", thus we've
    262  1.1.1.3  christos    never supported la.pcrel an external symbol unless the loaded address is
    263  1.1.1.3  christos    only used for locating a function to be called.  Thus the PLT entry is
    264  1.1.1.3  christos    a normal PLT entry, not intended to be a so-called "canonical PLT entry"
    265  1.1.1.3  christos    on the ports supporting copy relocation.  So attempting to la.pcrel an
    266  1.1.1.3  christos    external function will just break pointer equality, even it's a
    267  1.1.1.3  christos    STV_DEFAULT function:
    268  1.1.1.3  christos 
    269  1.1.1.3  christos    $ cat t.c
    270  1.1.1.3  christos    #include <assert.h>
    271  1.1.1.3  christos    void check(void *p) {assert(p == check);}
    272  1.1.1.3  christos    $ cat main.c
    273  1.1.1.3  christos    extern void check(void *);
    274  1.1.1.3  christos    int main(void) { check(check); }
    275  1.1.1.3  christos    $ cc t.c -fPIC -shared -o t.so
    276  1.1.1.3  christos    $ cc main.c -mdirect-extern-access t.so -Wl,-rpath=. -fpie -pie
    277  1.1.1.3  christos    $ ./a.out
    278  1.1.1.3  christos    a.out: t.c:2: check: Assertion `p == check' failed.
    279  1.1.1.3  christos    Aborted
    280  1.1.1.3  christos 
    281  1.1.1.3  christos    Thus handling STV_PROTECTED function specially just fixes nothing:
    282  1.1.1.3  christos    adding -fvisibility=protected compiling t.c will not magically fix
    283  1.1.1.3  christos    the inequality.  The only possible and correct fix is not to use
    284  1.1.1.3  christos    -mdirect-extern-access.
    285  1.1.1.3  christos 
    286  1.1.1.3  christos    So we should remove this special handling, because it's only an
    287  1.1.1.3  christos    unsuccessful workaround for invalid code and it's penalizing valid
    288  1.1.1.3  christos    code.  */
    289  1.1.1.3  christos #define LARCH_REF_LOCAL(info, h) \
    290  1.1.1.3  christos   (_bfd_elf_symbol_refs_local_p ((h), (info), true))
    291  1.1.1.3  christos 
    292      1.1  christos /* Generate a PLT header.  */
    293      1.1  christos 
    294      1.1  christos static bool
    295      1.1  christos loongarch_make_plt_header (bfd_vma got_plt_addr, bfd_vma plt_header_addr,
    296      1.1  christos 			   uint32_t *entry)
    297      1.1  christos {
    298      1.1  christos   bfd_vma pcrel = got_plt_addr - plt_header_addr;
    299      1.1  christos   bfd_vma hi, lo;
    300      1.1  christos 
    301      1.1  christos   if (pcrel + 0x80000800 > 0xffffffff)
    302      1.1  christos     {
    303      1.1  christos       _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
    304      1.1  christos       bfd_set_error (bfd_error_bad_value);
    305      1.1  christos       return false;
    306      1.1  christos     }
    307      1.1  christos   hi = ((pcrel + 0x800) >> 12) & 0xfffff;
    308      1.1  christos   lo = pcrel & 0xfff;
    309      1.1  christos 
    310      1.1  christos   /* pcaddu12i  $t2, %hi(%pcrel(.got.plt))
    311      1.1  christos      sub.[wd]   $t1, $t1, $t3
    312      1.1  christos      ld.[wd]    $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
    313      1.1  christos      addi.[wd]  $t1, $t1, -(PLT_HEADER_SIZE + 12)
    314      1.1  christos      addi.[wd]  $t0, $t2, %lo(%pcrel(.got.plt))
    315      1.1  christos      srli.[wd]  $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
    316      1.1  christos      ld.[wd]    $t0, $t0, GOT_ENTRY_SIZE
    317      1.1  christos      jirl   $r0, $t3, 0 */
    318      1.1  christos 
    319      1.1  christos   if (GOT_ENTRY_SIZE == 8)
    320      1.1  christos     {
    321      1.1  christos       entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
    322      1.1  christos       entry[1] = 0x0011bdad;
    323      1.1  christos       entry[2] = 0x28c001cf | (lo & 0xfff) << 10;
    324      1.1  christos       entry[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
    325      1.1  christos       entry[4] = 0x02c001cc | (lo & 0xfff) << 10;
    326      1.1  christos       entry[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
    327      1.1  christos       entry[6] = 0x28c0018c | GOT_ENTRY_SIZE << 10;
    328      1.1  christos       entry[7] = 0x4c0001e0;
    329      1.1  christos     }
    330      1.1  christos   else
    331      1.1  christos     {
    332      1.1  christos       entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
    333      1.1  christos       entry[1] = 0x00113dad;
    334      1.1  christos       entry[2] = 0x288001cf | (lo & 0xfff) << 10;
    335      1.1  christos       entry[3] = 0x028001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
    336      1.1  christos       entry[4] = 0x028001cc | (lo & 0xfff) << 10;
    337      1.1  christos       entry[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
    338      1.1  christos       entry[6] = 0x2880018c | GOT_ENTRY_SIZE << 10;
    339      1.1  christos       entry[7] = 0x4c0001e0;
    340      1.1  christos     }
    341      1.1  christos   return true;
    342      1.1  christos }
    343      1.1  christos 
    344      1.1  christos /* Generate a PLT entry.  */
    345      1.1  christos 
    346      1.1  christos static bool
    347      1.1  christos loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, bfd_vma plt_entry_addr,
    348      1.1  christos 			  uint32_t *entry)
    349      1.1  christos {
    350      1.1  christos   bfd_vma pcrel = got_plt_entry_addr - plt_entry_addr;
    351      1.1  christos   bfd_vma hi, lo;
    352      1.1  christos 
    353      1.1  christos   if (pcrel + 0x80000800 > 0xffffffff)
    354      1.1  christos     {
    355      1.1  christos       _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t) pcrel);
    356      1.1  christos       bfd_set_error (bfd_error_bad_value);
    357      1.1  christos       return false;
    358      1.1  christos     }
    359      1.1  christos   hi = ((pcrel + 0x800) >> 12) & 0xfffff;
    360      1.1  christos   lo = pcrel & 0xfff;
    361      1.1  christos 
    362      1.1  christos   entry[0] = 0x1c00000f | (hi & 0xfffff) << 5;
    363      1.1  christos   entry[1] = ((GOT_ENTRY_SIZE == 8 ? 0x28c001ef : 0x288001ef)
    364      1.1  christos 	      | (lo & 0xfff) << 10);
    365      1.1  christos   entry[2] = 0x4c0001ed;	/* jirl $r13, $15, 0 */
    366      1.1  christos   entry[3] = 0x03400000;	/* nop */
    367      1.1  christos 
    368      1.1  christos   return true;
    369      1.1  christos }
    370      1.1  christos 
    371      1.1  christos /* Create an entry in an LoongArch ELF linker hash table.  */
    372      1.1  christos 
    373      1.1  christos static struct bfd_hash_entry *
    374      1.1  christos link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
    375      1.1  christos 		   const char *string)
    376      1.1  christos {
    377      1.1  christos   struct loongarch_elf_link_hash_entry *eh;
    378      1.1  christos 
    379      1.1  christos   /* Allocate the structure if it has not already been allocated by a
    380      1.1  christos      subclass.  */
    381      1.1  christos   if (entry == NULL)
    382      1.1  christos     {
    383      1.1  christos       entry = bfd_hash_allocate (table, sizeof (*eh));
    384      1.1  christos       if (entry == NULL)
    385      1.1  christos 	return entry;
    386      1.1  christos     }
    387      1.1  christos 
    388      1.1  christos   /* Call the allocation method of the superclass.  */
    389      1.1  christos   entry = _bfd_elf_link_hash_newfunc (entry, table, string);
    390      1.1  christos   if (entry != NULL)
    391      1.1  christos     {
    392      1.1  christos       eh = (struct loongarch_elf_link_hash_entry *) entry;
    393      1.1  christos       eh->tls_type = GOT_UNKNOWN;
    394      1.1  christos     }
    395      1.1  christos 
    396      1.1  christos   return entry;
    397      1.1  christos }
    398      1.1  christos 
    399      1.1  christos /* Compute a hash of a local hash entry.  We use elf_link_hash_entry
    400      1.1  christos   for local symbol so that we can handle local STT_GNU_IFUNC symbols
    401      1.1  christos   as global symbol.  We reuse indx and dynstr_index for local symbol
    402      1.1  christos   hash since they aren't used by global symbols in this backend.  */
    403      1.1  christos 
    404      1.1  christos static hashval_t
    405      1.1  christos elfNN_loongarch_local_htab_hash (const void *ptr)
    406      1.1  christos {
    407      1.1  christos   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr;
    408      1.1  christos   return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
    409      1.1  christos }
    410      1.1  christos 
    411      1.1  christos /* Compare local hash entries.  */
    412      1.1  christos 
    413      1.1  christos static int
    414      1.1  christos elfNN_loongarch_local_htab_eq (const void *ptr1, const void *ptr2)
    415      1.1  christos {
    416      1.1  christos   struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1;
    417      1.1  christos   struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2;
    418      1.1  christos 
    419      1.1  christos   return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
    420      1.1  christos }
    421      1.1  christos 
    422      1.1  christos /* Find and/or create a hash entry for local symbol.  */
    423      1.1  christos static struct elf_link_hash_entry *
    424      1.1  christos elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table *htab,
    425      1.1  christos 				    bfd *abfd, const Elf_Internal_Rela *rel,
    426      1.1  christos 				    bool create)
    427      1.1  christos {
    428      1.1  christos   struct loongarch_elf_link_hash_entry e, *ret;
    429      1.1  christos   asection *sec = abfd->sections;
    430      1.1  christos   hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, ELFNN_R_SYM (rel->r_info));
    431      1.1  christos   void **slot;
    432      1.1  christos 
    433      1.1  christos   e.elf.indx = sec->id;
    434      1.1  christos   e.elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
    435      1.1  christos   slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
    436      1.1  christos 				   create ? INSERT : NO_INSERT);
    437      1.1  christos 
    438      1.1  christos   if (!slot)
    439      1.1  christos     return NULL;
    440      1.1  christos 
    441      1.1  christos   if (*slot)
    442      1.1  christos     {
    443      1.1  christos       ret = (struct loongarch_elf_link_hash_entry *) *slot;
    444      1.1  christos       return &ret->elf;
    445      1.1  christos     }
    446      1.1  christos 
    447      1.1  christos   ret = ((struct loongarch_elf_link_hash_entry *)
    448      1.1  christos 	 objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
    449      1.1  christos 			 sizeof (struct loongarch_elf_link_hash_entry)));
    450      1.1  christos   if (ret)
    451      1.1  christos     {
    452      1.1  christos       memset (ret, 0, sizeof (*ret));
    453      1.1  christos       ret->elf.indx = sec->id;
    454      1.1  christos       ret->elf.pointer_equality_needed = 0;
    455      1.1  christos       ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
    456      1.1  christos       ret->elf.dynindx = -1;
    457      1.1  christos       ret->elf.needs_plt = 0;
    458      1.1  christos       ret->elf.plt.refcount = -1;
    459      1.1  christos       ret->elf.got.refcount = -1;
    460      1.1  christos       ret->elf.def_dynamic = 0;
    461      1.1  christos       ret->elf.def_regular = 1;
    462      1.1  christos       ret->elf.ref_dynamic = 0; /* This should be always 0 for local.  */
    463      1.1  christos       ret->elf.ref_regular = 0;
    464      1.1  christos       ret->elf.forced_local = 1;
    465      1.1  christos       ret->elf.root.type = bfd_link_hash_defined;
    466      1.1  christos       *slot = ret;
    467      1.1  christos     }
    468      1.1  christos   return &ret->elf;
    469      1.1  christos }
    470      1.1  christos 
    471      1.1  christos /* Destroy an LoongArch elf linker hash table.  */
    472      1.1  christos 
    473      1.1  christos static void
    474      1.1  christos elfNN_loongarch_link_hash_table_free (bfd *obfd)
    475      1.1  christos {
    476      1.1  christos   struct loongarch_elf_link_hash_table *ret;
    477      1.1  christos   ret = (struct loongarch_elf_link_hash_table *) obfd->link.hash;
    478      1.1  christos 
    479      1.1  christos   if (ret->loc_hash_table)
    480      1.1  christos     htab_delete (ret->loc_hash_table);
    481      1.1  christos   if (ret->loc_hash_memory)
    482      1.1  christos     objalloc_free ((struct objalloc *) ret->loc_hash_memory);
    483      1.1  christos 
    484      1.1  christos   _bfd_elf_link_hash_table_free (obfd);
    485      1.1  christos }
    486      1.1  christos 
    487      1.1  christos /* Create a LoongArch ELF linker hash table.  */
    488      1.1  christos 
    489      1.1  christos static struct bfd_link_hash_table *
    490      1.1  christos loongarch_elf_link_hash_table_create (bfd *abfd)
    491      1.1  christos {
    492      1.1  christos   struct loongarch_elf_link_hash_table *ret;
    493      1.1  christos   bfd_size_type amt = sizeof (struct loongarch_elf_link_hash_table);
    494      1.1  christos 
    495      1.1  christos   ret = (struct loongarch_elf_link_hash_table *) bfd_zmalloc (amt);
    496      1.1  christos   if (ret == NULL)
    497      1.1  christos     return NULL;
    498      1.1  christos 
    499      1.1  christos   if (!_bfd_elf_link_hash_table_init
    500      1.1  christos       (&ret->elf, abfd, link_hash_newfunc,
    501  1.1.1.3  christos        sizeof (struct loongarch_elf_link_hash_entry)))
    502      1.1  christos     {
    503      1.1  christos       free (ret);
    504      1.1  christos       return NULL;
    505      1.1  christos     }
    506      1.1  christos 
    507      1.1  christos   ret->max_alignment = MINUS_ONE;
    508      1.1  christos 
    509      1.1  christos   ret->loc_hash_table = htab_try_create (1024, elfNN_loongarch_local_htab_hash,
    510      1.1  christos 					 elfNN_loongarch_local_htab_eq, NULL);
    511      1.1  christos   ret->loc_hash_memory = objalloc_create ();
    512      1.1  christos   if (!ret->loc_hash_table || !ret->loc_hash_memory)
    513      1.1  christos     {
    514      1.1  christos       elfNN_loongarch_link_hash_table_free (abfd);
    515      1.1  christos       return NULL;
    516      1.1  christos     }
    517      1.1  christos   ret->elf.root.hash_table_free = elfNN_loongarch_link_hash_table_free;
    518      1.1  christos 
    519      1.1  christos   return &ret->elf.root;
    520      1.1  christos }
    521      1.1  christos 
    522      1.1  christos /* Merge backend specific data from an object file to the output
    523      1.1  christos    object file when linking.  */
    524      1.1  christos 
    525      1.1  christos static bool
    526      1.1  christos elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
    527      1.1  christos {
    528      1.1  christos   bfd *obfd = info->output_bfd;
    529      1.1  christos   flagword in_flags = elf_elfheader (ibfd)->e_flags;
    530      1.1  christos   flagword out_flags = elf_elfheader (obfd)->e_flags;
    531      1.1  christos 
    532      1.1  christos   if (!is_loongarch_elf (ibfd) || !is_loongarch_elf (obfd))
    533      1.1  christos     return true;
    534      1.1  christos 
    535      1.1  christos   if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
    536      1.1  christos     {
    537      1.1  christos       _bfd_error_handler (_("%pB: ABI is incompatible with that of "
    538      1.1  christos 			    "the selected emulation:\n"
    539      1.1  christos 			    "  target emulation `%s' does not match `%s'"),
    540      1.1  christos 			  ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
    541      1.1  christos       return false;
    542      1.1  christos     }
    543      1.1  christos 
    544      1.1  christos   if (!_bfd_elf_merge_object_attributes (ibfd, info))
    545      1.1  christos     return false;
    546      1.1  christos 
    547      1.1  christos   /* If the input BFD is not a dynamic object and it does not contain any
    548      1.1  christos      non-data sections, do not account its ABI.  For example, various
    549      1.1  christos      packages produces such data-only relocatable objects with
    550      1.1  christos      `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
    551      1.1  christos      But they are compatible with all ABIs.  */
    552      1.1  christos   if (!(ibfd->flags & DYNAMIC))
    553      1.1  christos     {
    554      1.1  christos       asection *sec;
    555      1.1  christos       bool have_code_sections = false;
    556      1.1  christos       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
    557      1.1  christos 	if ((bfd_section_flags (sec)
    558      1.1  christos 	     & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
    559      1.1  christos 	    == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
    560      1.1  christos 	  {
    561      1.1  christos 	    have_code_sections = true;
    562      1.1  christos 	    break;
    563      1.1  christos 	  }
    564      1.1  christos       if (!have_code_sections)
    565      1.1  christos 	return true;
    566      1.1  christos     }
    567      1.1  christos 
    568      1.1  christos   if (!elf_flags_init (obfd))
    569      1.1  christos     {
    570      1.1  christos       elf_flags_init (obfd) = true;
    571      1.1  christos       elf_elfheader (obfd)->e_flags = in_flags;
    572      1.1  christos       return true;
    573      1.1  christos     }
    574  1.1.1.2  christos   else if (out_flags != in_flags)
    575  1.1.1.2  christos     {
    576  1.1.1.2  christos       if ((EF_LOONGARCH_IS_OBJ_V0 (out_flags)
    577  1.1.1.2  christos 	   && EF_LOONGARCH_IS_OBJ_V1 (in_flags))
    578  1.1.1.2  christos 	  || (EF_LOONGARCH_IS_OBJ_V0 (in_flags)
    579  1.1.1.2  christos 	      && EF_LOONGARCH_IS_OBJ_V1 (out_flags)))
    580  1.1.1.2  christos 	{
    581  1.1.1.2  christos 	  elf_elfheader (obfd)->e_flags |= EF_LOONGARCH_OBJABI_V1;
    582  1.1.1.2  christos 	  out_flags = elf_elfheader (obfd)->e_flags;
    583  1.1.1.2  christos 	  in_flags = out_flags;
    584  1.1.1.2  christos 	}
    585  1.1.1.2  christos     }
    586      1.1  christos 
    587      1.1  christos   /* Disallow linking different ABIs.  */
    588  1.1.1.2  christos   /* Only check relocation version.
    589  1.1.1.2  christos      The obj_v0 is compatible with obj_v1.  */
    590      1.1  christos   if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
    591      1.1  christos     {
    592      1.1  christos       _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd);
    593      1.1  christos       goto fail;
    594      1.1  christos     }
    595      1.1  christos 
    596      1.1  christos   return true;
    597      1.1  christos 
    598      1.1  christos  fail:
    599      1.1  christos   bfd_set_error (bfd_error_bad_value);
    600      1.1  christos   return false;
    601      1.1  christos }
    602      1.1  christos 
    603      1.1  christos /* Create the .got section.  */
    604      1.1  christos 
    605      1.1  christos static bool
    606      1.1  christos loongarch_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
    607      1.1  christos {
    608      1.1  christos   flagword flags;
    609      1.1  christos   char *name;
    610      1.1  christos   asection *s, *s_got;
    611      1.1  christos   struct elf_link_hash_entry *h;
    612      1.1  christos   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
    613      1.1  christos   struct elf_link_hash_table *htab = elf_hash_table (info);
    614      1.1  christos 
    615      1.1  christos   /* This function may be called more than once.  */
    616      1.1  christos   if (htab->sgot != NULL)
    617      1.1  christos     return true;
    618      1.1  christos 
    619      1.1  christos   flags = bed->dynamic_sec_flags;
    620      1.1  christos   name = bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got";
    621      1.1  christos   s = bfd_make_section_anyway_with_flags (abfd, name, flags | SEC_READONLY);
    622      1.1  christos 
    623      1.1  christos   if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
    624      1.1  christos     return false;
    625      1.1  christos   htab->srelgot = s;
    626      1.1  christos 
    627      1.1  christos   s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
    628      1.1  christos   if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
    629      1.1  christos     return false;
    630      1.1  christos   htab->sgot = s;
    631      1.1  christos 
    632      1.1  christos   /* The first bit of the global offset table is the header.  */
    633      1.1  christos   s->size += bed->got_header_size;
    634      1.1  christos 
    635      1.1  christos   if (bed->want_got_plt)
    636      1.1  christos     {
    637      1.1  christos       s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
    638      1.1  christos       if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
    639      1.1  christos 	return false;
    640      1.1  christos       htab->sgotplt = s;
    641      1.1  christos 
    642      1.1  christos       /* Reserve room for the header.  */
    643      1.1  christos       s->size = GOTPLT_HEADER_SIZE;
    644      1.1  christos     }
    645      1.1  christos 
    646      1.1  christos   if (bed->want_got_sym)
    647      1.1  christos     {
    648      1.1  christos       /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
    649      1.1  christos 	 section.  We don't do this in the linker script because we don't want
    650      1.1  christos 	 to define the symbol if we are not creating a global offset table.  */
    651      1.1  christos       h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
    652      1.1  christos 				       "_GLOBAL_OFFSET_TABLE_");
    653      1.1  christos       elf_hash_table (info)->hgot = h;
    654      1.1  christos       if (h == NULL)
    655      1.1  christos 	return false;
    656      1.1  christos     }
    657      1.1  christos   return true;
    658      1.1  christos }
    659      1.1  christos 
    660      1.1  christos /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
    661      1.1  christos    .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
    662      1.1  christos    hash table.  */
    663      1.1  christos 
    664      1.1  christos static bool
    665      1.1  christos loongarch_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
    666      1.1  christos {
    667      1.1  christos   struct loongarch_elf_link_hash_table *htab;
    668      1.1  christos 
    669      1.1  christos   htab = loongarch_elf_hash_table (info);
    670      1.1  christos   BFD_ASSERT (htab != NULL);
    671      1.1  christos 
    672      1.1  christos   if (!loongarch_elf_create_got_section (dynobj, info))
    673      1.1  christos     return false;
    674      1.1  christos 
    675      1.1  christos   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
    676      1.1  christos     return false;
    677      1.1  christos 
    678      1.1  christos   if (!bfd_link_pic (info))
    679      1.1  christos     htab->sdyntdata
    680      1.1  christos       = bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
    681      1.1  christos 					    SEC_ALLOC | SEC_THREAD_LOCAL);
    682      1.1  christos 
    683      1.1  christos   if (!htab->elf.splt || !htab->elf.srelplt || !htab->elf.sdynbss
    684      1.1  christos       || (!bfd_link_pic (info) && (!htab->elf.srelbss || !htab->sdyntdata)))
    685      1.1  christos     abort ();
    686      1.1  christos 
    687      1.1  christos   return true;
    688      1.1  christos }
    689      1.1  christos 
    690      1.1  christos static bool
    691      1.1  christos loongarch_elf_record_tls_and_got_reference (bfd *abfd,
    692      1.1  christos 					    struct bfd_link_info *info,
    693      1.1  christos 					    struct elf_link_hash_entry *h,
    694      1.1  christos 					    unsigned long symndx,
    695  1.1.1.3  christos 					    char tls_type,
    696  1.1.1.3  christos 					    bool with_relax_reloc)
    697      1.1  christos {
    698      1.1  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
    699      1.1  christos   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    700      1.1  christos 
    701      1.1  christos   /* This is a global offset table entry for a local symbol.  */
    702      1.1  christos   if (elf_local_got_refcounts (abfd) == NULL)
    703      1.1  christos     {
    704      1.1  christos       bfd_size_type size =
    705      1.1  christos 	symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (tls_type));
    706      1.1  christos       if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
    707      1.1  christos 	return false;
    708      1.1  christos       _bfd_loongarch_elf_local_got_tls_type (abfd) =
    709      1.1  christos 	(char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
    710      1.1  christos     }
    711      1.1  christos 
    712      1.1  christos   switch (tls_type)
    713      1.1  christos     {
    714      1.1  christos     case GOT_NORMAL:
    715      1.1  christos     case GOT_TLS_GD:
    716      1.1  christos     case GOT_TLS_IE:
    717  1.1.1.2  christos     case GOT_TLS_GDESC:
    718      1.1  christos       /* Need GOT.  */
    719      1.1  christos       if (htab->elf.sgot == NULL
    720      1.1  christos 	  && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
    721      1.1  christos 	return false;
    722      1.1  christos       if (h)
    723      1.1  christos 	{
    724      1.1  christos 	  if (h->got.refcount < 0)
    725      1.1  christos 	    h->got.refcount = 0;
    726      1.1  christos 	  h->got.refcount++;
    727      1.1  christos 	}
    728      1.1  christos       else
    729      1.1  christos 	elf_local_got_refcounts (abfd)[symndx]++;
    730      1.1  christos       break;
    731      1.1  christos     case GOT_TLS_LE:
    732      1.1  christos       /* No need for GOT.  */
    733      1.1  christos       break;
    734      1.1  christos     default:
    735      1.1  christos       _bfd_error_handler (_("Internal error: unreachable."));
    736      1.1  christos       return false;
    737      1.1  christos     }
    738      1.1  christos 
    739      1.1  christos   char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
    740      1.1  christos   *new_tls_type |= tls_type;
    741  1.1.1.2  christos 
    742  1.1.1.3  christos   /* If DESC relocs can do transitions and accessed by both IE and DESC,
    743  1.1.1.3  christos      transition DESC to IE.  */
    744  1.1.1.3  christos   if (with_relax_reloc
    745  1.1.1.3  christos       && (*new_tls_type & GOT_TLS_IE) && (*new_tls_type & GOT_TLS_GDESC))
    746  1.1.1.2  christos     *new_tls_type &= ~ (GOT_TLS_GDESC);
    747  1.1.1.3  christos 
    748      1.1  christos   if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
    749      1.1  christos     {
    750      1.1  christos       _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
    751      1.1  christos 			    "thread local symbol"),
    752      1.1  christos 			  abfd,
    753      1.1  christos 			  h ? h->root.root.string : "<local>");
    754      1.1  christos       return false;
    755      1.1  christos     }
    756      1.1  christos 
    757      1.1  christos   return true;
    758      1.1  christos }
    759      1.1  christos 
    760  1.1.1.2  christos static unsigned int
    761  1.1.1.2  christos loongarch_reloc_got_type (unsigned int r_type)
    762  1.1.1.2  christos {
    763  1.1.1.2  christos   switch (r_type)
    764  1.1.1.2  christos     {
    765  1.1.1.2  christos       case R_LARCH_TLS_DESC_PC_HI20:
    766  1.1.1.2  christos       case R_LARCH_TLS_DESC_PC_LO12:
    767  1.1.1.2  christos       case R_LARCH_TLS_DESC_LD:
    768  1.1.1.2  christos       case R_LARCH_TLS_DESC_CALL:
    769  1.1.1.2  christos 	return GOT_TLS_GDESC;
    770  1.1.1.2  christos 
    771  1.1.1.2  christos       case R_LARCH_TLS_IE_PC_HI20:
    772  1.1.1.2  christos       case R_LARCH_TLS_IE_PC_LO12:
    773  1.1.1.2  christos 	return GOT_TLS_IE;
    774  1.1.1.2  christos 
    775  1.1.1.2  christos       default:
    776  1.1.1.2  christos 	break;
    777  1.1.1.2  christos     }
    778  1.1.1.2  christos   return GOT_UNKNOWN;
    779  1.1.1.2  christos }
    780  1.1.1.2  christos 
    781  1.1.1.2  christos /* Return true if tls type transition can be performed.  */
    782  1.1.1.2  christos static bool
    783  1.1.1.2  christos loongarch_can_trans_tls (bfd *input_bfd,
    784  1.1.1.3  christos 			 struct bfd_link_info *info,
    785  1.1.1.3  christos 			 struct elf_link_hash_entry *h,
    786  1.1.1.3  christos 			 unsigned int r_symndx,
    787  1.1.1.3  christos 			 unsigned int r_type)
    788  1.1.1.2  christos {
    789  1.1.1.2  christos   char symbol_tls_type;
    790  1.1.1.2  christos   unsigned int reloc_got_type;
    791  1.1.1.2  christos 
    792  1.1.1.2  christos   /* Only TLS DESC/IE in normal code mode will perform type
    793  1.1.1.2  christos      transition.  */
    794  1.1.1.3  christos   if (! IS_LOONGARCH_TLS_TRANS_RELOC (r_type))
    795  1.1.1.2  christos     return false;
    796  1.1.1.2  christos 
    797  1.1.1.3  christos   /* Obtaining tls got type here may occur before
    798  1.1.1.3  christos      loongarch_elf_record_tls_and_got_reference, so it is necessary
    799  1.1.1.3  christos      to ensure that tls got type has been initialized, otherwise it
    800  1.1.1.3  christos      is set to GOT_UNKNOWN.  */
    801  1.1.1.3  christos   symbol_tls_type = GOT_UNKNOWN;
    802  1.1.1.3  christos   if (_bfd_loongarch_elf_local_got_tls_type (input_bfd) || h)
    803  1.1.1.3  christos     symbol_tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
    804  1.1.1.3  christos 
    805  1.1.1.2  christos   reloc_got_type = loongarch_reloc_got_type (r_type);
    806  1.1.1.2  christos 
    807  1.1.1.2  christos   if (symbol_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (reloc_got_type))
    808  1.1.1.2  christos     return true;
    809  1.1.1.2  christos 
    810  1.1.1.2  christos   if (! bfd_link_executable (info))
    811  1.1.1.2  christos       return false;
    812  1.1.1.2  christos 
    813  1.1.1.2  christos   if (h && h->root.type == bfd_link_hash_undefweak)
    814  1.1.1.2  christos     return false;
    815  1.1.1.2  christos 
    816  1.1.1.2  christos   return true;
    817  1.1.1.2  christos }
    818  1.1.1.2  christos 
    819  1.1.1.2  christos /* The type of relocation that can be transitioned.  */
    820  1.1.1.2  christos static unsigned int
    821  1.1.1.2  christos loongarch_tls_transition_without_check (struct bfd_link_info *info,
    822  1.1.1.2  christos 					unsigned int r_type,
    823  1.1.1.2  christos 					struct elf_link_hash_entry *h)
    824  1.1.1.2  christos {
    825  1.1.1.2  christos   bool local_exec = bfd_link_executable (info)
    826  1.1.1.3  christos 		    && LARCH_REF_LOCAL (info, h);
    827  1.1.1.2  christos 
    828  1.1.1.2  christos   switch (r_type)
    829  1.1.1.2  christos     {
    830  1.1.1.2  christos       case R_LARCH_TLS_DESC_PC_HI20:
    831  1.1.1.2  christos 	return (local_exec
    832  1.1.1.2  christos 		? R_LARCH_TLS_LE_HI20
    833  1.1.1.2  christos 		: R_LARCH_TLS_IE_PC_HI20);
    834  1.1.1.2  christos 
    835  1.1.1.2  christos       case R_LARCH_TLS_DESC_PC_LO12:
    836  1.1.1.2  christos 	return (local_exec
    837  1.1.1.2  christos 		? R_LARCH_TLS_LE_LO12
    838  1.1.1.2  christos 		: R_LARCH_TLS_IE_PC_LO12);
    839  1.1.1.2  christos 
    840  1.1.1.2  christos       case R_LARCH_TLS_DESC_LD:
    841  1.1.1.2  christos       case R_LARCH_TLS_DESC_CALL:
    842  1.1.1.2  christos 	return R_LARCH_NONE;
    843  1.1.1.2  christos 
    844  1.1.1.2  christos       case R_LARCH_TLS_IE_PC_HI20:
    845  1.1.1.2  christos 	return local_exec ? R_LARCH_TLS_LE_HI20 : r_type;
    846  1.1.1.2  christos 
    847  1.1.1.2  christos       case R_LARCH_TLS_IE_PC_LO12:
    848  1.1.1.2  christos 	return local_exec ? R_LARCH_TLS_LE_LO12 : r_type;
    849  1.1.1.2  christos 
    850  1.1.1.2  christos       default:
    851  1.1.1.2  christos 	break;
    852  1.1.1.2  christos     }
    853  1.1.1.2  christos 
    854  1.1.1.2  christos   return r_type;
    855  1.1.1.2  christos }
    856  1.1.1.2  christos 
    857  1.1.1.2  christos static unsigned int
    858  1.1.1.2  christos loongarch_tls_transition (bfd *input_bfd,
    859  1.1.1.2  christos 			  struct bfd_link_info *info,
    860  1.1.1.2  christos 			  struct elf_link_hash_entry *h,
    861  1.1.1.3  christos 			  unsigned int r_symndx,
    862  1.1.1.2  christos 			  unsigned int r_type)
    863  1.1.1.2  christos {
    864  1.1.1.3  christos   if (! loongarch_can_trans_tls (input_bfd, info, h, r_symndx, r_type))
    865  1.1.1.2  christos     return r_type;
    866  1.1.1.2  christos 
    867  1.1.1.2  christos   return loongarch_tls_transition_without_check (info, r_type, h);
    868  1.1.1.2  christos }
    869  1.1.1.2  christos 
    870  1.1.1.3  christos static bool
    871  1.1.1.3  christos bad_static_reloc (struct bfd_link_info *info,
    872  1.1.1.3  christos 		  bfd *abfd, const Elf_Internal_Rela *rel,
    873  1.1.1.3  christos 		  asection *sec, unsigned r_type,
    874  1.1.1.3  christos 		  struct elf_link_hash_entry *h,
    875  1.1.1.3  christos 		  Elf_Internal_Sym *isym)
    876  1.1.1.3  christos {
    877  1.1.1.3  christos   reloc_howto_type * r = loongarch_elf_rtype_to_howto (abfd, r_type);
    878  1.1.1.3  christos   const char *object;
    879  1.1.1.3  christos   const char *pic_opt;
    880  1.1.1.3  christos   const char *name = NULL;
    881  1.1.1.3  christos 
    882  1.1.1.3  christos   /* If this, the problem is we are referring an external symbol in
    883  1.1.1.3  christos      a way only working for local symbols, not PC-relative vs.
    884  1.1.1.3  christos 	 absolute.  */
    885  1.1.1.3  christos   bool bad_extern_access =
    886  1.1.1.3  christos     (bfd_link_pde (info)
    887  1.1.1.3  christos      || r_type == R_LARCH_PCREL20_S2
    888  1.1.1.3  christos      || r_type == R_LARCH_PCALA_HI20);
    889  1.1.1.3  christos 
    890  1.1.1.3  christos   if (h)
    891  1.1.1.3  christos     name = h->root.root.string;
    892  1.1.1.3  christos   else if (isym)
    893  1.1.1.3  christos     name = bfd_elf_string_from_elf_section (abfd,
    894  1.1.1.3  christos 					    elf_symtab_hdr (abfd).sh_link,
    895  1.1.1.3  christos 					    isym->st_name);
    896  1.1.1.3  christos   if (name == NULL || *name == '\0')
    897  1.1.1.3  christos     name = "<nameless>";
    898  1.1.1.3  christos 
    899  1.1.1.3  christos   if (bfd_link_dll (info))
    900  1.1.1.3  christos     {
    901  1.1.1.3  christos       object = _("a shared object");
    902  1.1.1.3  christos       pic_opt = "-fPIC";
    903  1.1.1.3  christos     }
    904  1.1.1.3  christos   else
    905  1.1.1.3  christos     {
    906  1.1.1.3  christos       if (bfd_link_pie (info))
    907  1.1.1.3  christos 	object = _("a PIE object");
    908  1.1.1.3  christos       else
    909  1.1.1.3  christos 	object = _("a PDE object");
    910  1.1.1.3  christos 
    911  1.1.1.3  christos       pic_opt = bad_extern_access ? "-mno-direct-extern-access" : "-fPIE";
    912  1.1.1.3  christos     }
    913  1.1.1.3  christos 
    914  1.1.1.3  christos   (*_bfd_error_handler)
    915  1.1.1.3  christos    (_("%pB:(%pA+%#lx): relocation %s against `%s` can not be used when making "
    916  1.1.1.3  christos       "%s; recompile with %s%s"),
    917  1.1.1.3  christos     abfd, sec, (long) rel->r_offset, r ? r->name : _("<unknown>"), name,
    918  1.1.1.3  christos     object, pic_opt,
    919  1.1.1.3  christos     bad_extern_access ? _(" and check the symbol visibility") : "");
    920  1.1.1.3  christos   bfd_set_error (bfd_error_bad_value);
    921  1.1.1.3  christos   return false;
    922  1.1.1.3  christos }
    923  1.1.1.3  christos 
    924      1.1  christos /* Look through the relocs for a section during the first phase, and
    925      1.1  christos    allocate space in the global offset table or procedure linkage
    926      1.1  christos    table.  */
    927      1.1  christos 
    928      1.1  christos static bool
    929      1.1  christos loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
    930      1.1  christos 			    asection *sec, const Elf_Internal_Rela *relocs)
    931      1.1  christos {
    932      1.1  christos   struct loongarch_elf_link_hash_table *htab;
    933      1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    934      1.1  christos   struct elf_link_hash_entry **sym_hashes;
    935      1.1  christos   const Elf_Internal_Rela *rel;
    936      1.1  christos   asection *sreloc = NULL;
    937      1.1  christos 
    938      1.1  christos   if (bfd_link_relocatable (info))
    939      1.1  christos     return true;
    940      1.1  christos 
    941      1.1  christos   htab = loongarch_elf_hash_table (info);
    942      1.1  christos   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    943      1.1  christos   sym_hashes = elf_sym_hashes (abfd);
    944      1.1  christos 
    945      1.1  christos   if (htab->elf.dynobj == NULL)
    946      1.1  christos     htab->elf.dynobj = abfd;
    947      1.1  christos 
    948      1.1  christos   for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
    949      1.1  christos     {
    950      1.1  christos       unsigned int r_type;
    951      1.1  christos       unsigned int r_symndx;
    952      1.1  christos       struct elf_link_hash_entry *h;
    953  1.1.1.3  christos       bool is_abs_symbol = false;
    954      1.1  christos       Elf_Internal_Sym *isym = NULL;
    955      1.1  christos 
    956      1.1  christos       r_symndx = ELFNN_R_SYM (rel->r_info);
    957      1.1  christos       r_type = ELFNN_R_TYPE (rel->r_info);
    958      1.1  christos 
    959      1.1  christos       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
    960      1.1  christos 	{
    961      1.1  christos 	  _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx);
    962      1.1  christos 	  return false;
    963      1.1  christos 	}
    964      1.1  christos 
    965      1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    966      1.1  christos 	{
    967      1.1  christos 	  /* A local symbol.  */
    968  1.1.1.2  christos 	  isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
    969      1.1  christos 	  if (isym == NULL)
    970      1.1  christos 	    return false;
    971      1.1  christos 
    972  1.1.1.3  christos 	  is_abs_symbol = isym->st_shndx == SHN_ABS;
    973      1.1  christos 	  if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
    974      1.1  christos 	    {
    975      1.1  christos 	      h = elfNN_loongarch_get_local_sym_hash (htab, abfd, rel, true);
    976      1.1  christos 	      if (h == NULL)
    977      1.1  christos 		return false;
    978      1.1  christos 
    979      1.1  christos 	      h->type = STT_GNU_IFUNC;
    980      1.1  christos 	      h->ref_regular = 1;
    981      1.1  christos 	    }
    982      1.1  christos 	  else
    983      1.1  christos 	    h = NULL;
    984      1.1  christos 	}
    985      1.1  christos       else
    986      1.1  christos 	{
    987      1.1  christos 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    988      1.1  christos 	  while (h->root.type == bfd_link_hash_indirect
    989      1.1  christos 		 || h->root.type == bfd_link_hash_warning)
    990      1.1  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    991  1.1.1.3  christos 	  is_abs_symbol = bfd_is_abs_symbol (&h->root);
    992      1.1  christos 	}
    993      1.1  christos 
    994      1.1  christos       /* It is referenced by a non-shared object.  */
    995      1.1  christos       if (h != NULL)
    996      1.1  christos 	h->ref_regular = 1;
    997      1.1  christos 
    998      1.1  christos       if (h && h->type == STT_GNU_IFUNC)
    999      1.1  christos 	{
   1000      1.1  christos 	  if (htab->elf.dynobj == NULL)
   1001      1.1  christos 	    htab->elf.dynobj = abfd;
   1002      1.1  christos 
   1003  1.1.1.2  christos 	  /* Create 'irelifunc' in PIC object.  */
   1004  1.1.1.2  christos 	  if (bfd_link_pic (info)
   1005  1.1.1.2  christos 	      && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
   1006  1.1.1.2  christos 	    return false;
   1007  1.1.1.2  christos 	  /* If '.plt' not represent, create '.iplt' to deal with ifunc.  */
   1008  1.1.1.2  christos 	  else if (!htab->elf.splt
   1009  1.1.1.2  christos 		   && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
   1010  1.1.1.2  christos 	    return false;
   1011      1.1  christos 	  /* Create the ifunc sections, iplt and ipltgot, for static
   1012      1.1  christos 	     executables.  */
   1013      1.1  christos 	  if ((r_type == R_LARCH_64 || r_type == R_LARCH_32)
   1014      1.1  christos 	      && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
   1015      1.1  christos 	    return false;
   1016      1.1  christos 
   1017      1.1  christos 	  if (h->plt.refcount < 0)
   1018      1.1  christos 	    h->plt.refcount = 0;
   1019      1.1  christos 	  h->plt.refcount++;
   1020      1.1  christos 	  h->needs_plt = 1;
   1021      1.1  christos 
   1022      1.1  christos 	  elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
   1023      1.1  christos 	}
   1024      1.1  christos 
   1025  1.1.1.2  christos       int need_dynreloc = 0;
   1026  1.1.1.2  christos       int only_need_pcrel = 0;
   1027  1.1.1.2  christos 
   1028  1.1.1.2  christos       /* Type transitions are only possible with relocations accompanied
   1029  1.1.1.2  christos 	 by R_LARCH_RELAX.  */
   1030  1.1.1.3  christos       bool with_relax_reloc = false;
   1031  1.1.1.3  christos       if (rel + 1 != relocs + sec->reloc_count
   1032  1.1.1.3  christos 	  && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX)
   1033  1.1.1.3  christos 	{
   1034  1.1.1.3  christos 	  r_type = loongarch_tls_transition (abfd, info, h, r_symndx, r_type);
   1035  1.1.1.3  christos 	  with_relax_reloc = true;
   1036  1.1.1.3  christos 	}
   1037  1.1.1.3  christos 
   1038  1.1.1.3  christos       /* I don't want to spend time supporting DT_RELR with old object
   1039  1.1.1.3  christos 	 files doing stack-based relocs.  */
   1040  1.1.1.3  christos       if (info->enable_dt_relr
   1041  1.1.1.3  christos 	  && r_type >= R_LARCH_SOP_PUSH_PCREL
   1042  1.1.1.3  christos 	  && r_type <= R_LARCH_SOP_POP_32_U)
   1043  1.1.1.3  christos 	{
   1044  1.1.1.3  christos 	  /* xgettext:c-format */
   1045  1.1.1.3  christos 	  _bfd_error_handler (_("%pB: stack based reloc type (%u) is not "
   1046  1.1.1.3  christos 				"supported with -z pack-relative-relocs"),
   1047  1.1.1.3  christos 			      abfd, r_type);
   1048  1.1.1.3  christos 	  return false;
   1049  1.1.1.3  christos 	}
   1050  1.1.1.3  christos 
   1051      1.1  christos       switch (r_type)
   1052      1.1  christos 	{
   1053  1.1.1.2  christos 	case R_LARCH_GOT_PC_HI20:
   1054  1.1.1.2  christos 	case R_LARCH_GOT_HI20:
   1055      1.1  christos 	case R_LARCH_SOP_PUSH_GPREL:
   1056  1.1.1.2  christos 	  /* For la.global.  */
   1057  1.1.1.2  christos 	  if (h)
   1058  1.1.1.2  christos 	    h->pointer_equality_needed = 1;
   1059      1.1  christos 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
   1060      1.1  christos 							   r_symndx,
   1061  1.1.1.3  christos 							   GOT_NORMAL,
   1062  1.1.1.3  christos 							   with_relax_reloc))
   1063      1.1  christos 	    return false;
   1064      1.1  christos 	  break;
   1065      1.1  christos 
   1066  1.1.1.2  christos 	case R_LARCH_TLS_LD_PC_HI20:
   1067  1.1.1.2  christos 	case R_LARCH_TLS_LD_HI20:
   1068  1.1.1.2  christos 	case R_LARCH_TLS_GD_PC_HI20:
   1069  1.1.1.2  christos 	case R_LARCH_TLS_GD_HI20:
   1070      1.1  christos 	case R_LARCH_SOP_PUSH_TLS_GD:
   1071      1.1  christos 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
   1072      1.1  christos 							   r_symndx,
   1073  1.1.1.3  christos 							   GOT_TLS_GD,
   1074  1.1.1.3  christos 							   with_relax_reloc))
   1075      1.1  christos 	    return false;
   1076      1.1  christos 	  break;
   1077      1.1  christos 
   1078  1.1.1.2  christos 	case R_LARCH_TLS_IE_PC_HI20:
   1079  1.1.1.2  christos 	case R_LARCH_TLS_IE_HI20:
   1080      1.1  christos 	case R_LARCH_SOP_PUSH_TLS_GOT:
   1081      1.1  christos 	  if (bfd_link_pic (info))
   1082      1.1  christos 	    /* May fail for lazy-bind.  */
   1083      1.1  christos 	    info->flags |= DF_STATIC_TLS;
   1084      1.1  christos 
   1085      1.1  christos 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
   1086      1.1  christos 							   r_symndx,
   1087  1.1.1.3  christos 							   GOT_TLS_IE,
   1088  1.1.1.3  christos 							   with_relax_reloc))
   1089      1.1  christos 	    return false;
   1090      1.1  christos 	  break;
   1091      1.1  christos 
   1092  1.1.1.2  christos 	case R_LARCH_TLS_LE_HI20:
   1093  1.1.1.2  christos 	case R_LARCH_TLS_LE_HI20_R:
   1094      1.1  christos 	case R_LARCH_SOP_PUSH_TLS_TPREL:
   1095      1.1  christos 	  if (!bfd_link_executable (info))
   1096  1.1.1.3  christos 	    return bad_static_reloc (info, abfd, rel, sec, r_type, h, isym);
   1097      1.1  christos 
   1098      1.1  christos 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
   1099      1.1  christos 							   r_symndx,
   1100  1.1.1.3  christos 							   GOT_TLS_LE,
   1101  1.1.1.3  christos 							   with_relax_reloc))
   1102      1.1  christos 	    return false;
   1103      1.1  christos 	  break;
   1104      1.1  christos 
   1105  1.1.1.2  christos 	case R_LARCH_TLS_DESC_PC_HI20:
   1106  1.1.1.2  christos 	case R_LARCH_TLS_DESC_HI20:
   1107  1.1.1.2  christos 	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
   1108  1.1.1.2  christos 							   r_symndx,
   1109  1.1.1.3  christos 							   GOT_TLS_GDESC,
   1110  1.1.1.3  christos 							   with_relax_reloc))
   1111  1.1.1.2  christos 	    return false;
   1112  1.1.1.2  christos 	  break;
   1113  1.1.1.2  christos 
   1114  1.1.1.2  christos 	case R_LARCH_ABS_HI20:
   1115  1.1.1.3  christos 	  if (bfd_link_pic (info))
   1116  1.1.1.3  christos 	    return bad_static_reloc (info, abfd, rel, sec, r_type, h, isym);
   1117  1.1.1.3  christos 
   1118  1.1.1.3  christos 	  /* Fall through.  */
   1119      1.1  christos 	case R_LARCH_SOP_PUSH_ABSOLUTE:
   1120      1.1  christos 	  if (h != NULL)
   1121      1.1  christos 	    /* If this reloc is in a read-only section, we might
   1122      1.1  christos 	       need a copy reloc.  We can't check reliably at this
   1123      1.1  christos 	       stage whether the section is read-only, as input
   1124      1.1  christos 	       sections have not yet been mapped to output sections.
   1125      1.1  christos 	       Tentatively set the flag for now, and correct in
   1126      1.1  christos 	       adjust_dynamic_symbol.  */
   1127      1.1  christos 	    h->non_got_ref = 1;
   1128      1.1  christos 	  break;
   1129      1.1  christos 
   1130  1.1.1.3  christos 	/* Since shared library global symbols interpose, any
   1131  1.1.1.3  christos 	   PC-relative relocations against external symbols
   1132  1.1.1.3  christos 	   should not be used to build shared libraries.
   1133  1.1.1.3  christos 	   In static PIE undefined weak symbols may be allowed
   1134  1.1.1.3  christos 	   by rewriting pcaddi to addi.w if addend is in [-2048, 2048).  */
   1135  1.1.1.3  christos 	case R_LARCH_PCREL20_S2:
   1136  1.1.1.3  christos 	  if (bfd_link_pic (info)
   1137  1.1.1.3  christos 	      && (sec->flags & SEC_ALLOC) != 0
   1138  1.1.1.3  christos 	      && (sec->flags & SEC_READONLY) != 0
   1139  1.1.1.3  christos 	      && ! LARCH_REF_LOCAL (info, h)
   1140  1.1.1.3  christos 	      && (!info->nointerp
   1141  1.1.1.3  christos 		  || h->root.type != bfd_link_hash_undefweak))
   1142  1.1.1.3  christos 	    return bad_static_reloc (info, abfd, rel, sec, r_type, h, NULL);
   1143  1.1.1.3  christos 
   1144  1.1.1.3  christos 	  break;
   1145  1.1.1.3  christos 
   1146  1.1.1.2  christos 	/* For normal cmodel, pcalau12i + addi.d/w used to data.
   1147  1.1.1.2  christos 	   For first version medium cmodel, pcalau12i + jirl are used to
   1148  1.1.1.2  christos 	   function call, it need to creat PLT entry for STT_FUNC and
   1149  1.1.1.2  christos 	   STT_GNU_IFUNC type symbol.  */
   1150  1.1.1.2  christos 	case R_LARCH_PCALA_HI20:
   1151  1.1.1.2  christos 	  if (h != NULL && (STT_FUNC == h->type || STT_GNU_IFUNC == h->type))
   1152  1.1.1.2  christos 	    {
   1153  1.1.1.2  christos 	      /* For pcalau12i + jirl.  */
   1154  1.1.1.2  christos 	      h->needs_plt = 1;
   1155  1.1.1.2  christos 	      if (h->plt.refcount < 0)
   1156  1.1.1.2  christos 		h->plt.refcount = 0;
   1157  1.1.1.2  christos 	      h->plt.refcount++;
   1158  1.1.1.2  christos 
   1159  1.1.1.2  christos 	      h->non_got_ref = 1;
   1160  1.1.1.2  christos 	      h->pointer_equality_needed = 1;
   1161  1.1.1.2  christos 	    }
   1162  1.1.1.2  christos 
   1163  1.1.1.3  christos 	  /* PC-relative relocations are allowed For first version
   1164  1.1.1.3  christos 	     medium cmodel function call.  Those against undefined
   1165  1.1.1.3  christos 	     weak symbol are allowed for static PIE by rewritting
   1166  1.1.1.3  christos 	     pcalau12i to lu12i.w.  */
   1167  1.1.1.3  christos 	  if (h != NULL && !h->needs_plt
   1168  1.1.1.3  christos 	      && bfd_link_pic (info)
   1169  1.1.1.3  christos 	      && (sec->flags & SEC_ALLOC) != 0
   1170  1.1.1.3  christos 	      && (sec->flags & SEC_READONLY) != 0
   1171  1.1.1.3  christos 	      && ! LARCH_REF_LOCAL (info, h)
   1172  1.1.1.3  christos 	      && (!info->nointerp
   1173  1.1.1.3  christos 		  || h->root.type != bfd_link_hash_undefweak))
   1174  1.1.1.3  christos 	    return bad_static_reloc (info, abfd, rel, sec, r_type, h, NULL);
   1175  1.1.1.3  christos 
   1176  1.1.1.2  christos 	  break;
   1177  1.1.1.2  christos 
   1178  1.1.1.2  christos 	case R_LARCH_B16:
   1179  1.1.1.2  christos 	case R_LARCH_B21:
   1180  1.1.1.2  christos 	case R_LARCH_B26:
   1181  1.1.1.2  christos 	case R_LARCH_CALL36:
   1182  1.1.1.2  christos 	  if (h != NULL)
   1183  1.1.1.2  christos 	    {
   1184  1.1.1.2  christos 	      h->needs_plt = 1;
   1185  1.1.1.2  christos 	      if (!bfd_link_pic (info))
   1186  1.1.1.2  christos 		h->non_got_ref = 1;
   1187  1.1.1.2  christos 
   1188  1.1.1.2  christos 	      /* We try to create PLT stub for all non-local function.  */
   1189  1.1.1.2  christos 	      if (h->plt.refcount < 0)
   1190  1.1.1.2  christos 		h->plt.refcount = 0;
   1191  1.1.1.2  christos 	      h->plt.refcount++;
   1192  1.1.1.2  christos 	    }
   1193  1.1.1.2  christos 
   1194  1.1.1.2  christos 	  break;
   1195  1.1.1.2  christos 
   1196      1.1  christos 	case R_LARCH_SOP_PUSH_PCREL:
   1197      1.1  christos 	  if (h != NULL)
   1198      1.1  christos 	    {
   1199  1.1.1.2  christos 	      if (!bfd_link_pic (info))
   1200  1.1.1.2  christos 		h->non_got_ref = 1;
   1201      1.1  christos 
   1202      1.1  christos 	      /* We try to create PLT stub for all non-local function.  */
   1203      1.1  christos 	      if (h->plt.refcount < 0)
   1204      1.1  christos 		h->plt.refcount = 0;
   1205      1.1  christos 	      h->plt.refcount++;
   1206  1.1.1.2  christos 	      h->pointer_equality_needed = 1;
   1207      1.1  christos 	    }
   1208  1.1.1.2  christos 
   1209      1.1  christos 	  break;
   1210      1.1  christos 
   1211      1.1  christos 	case R_LARCH_SOP_PUSH_PLT_PCREL:
   1212      1.1  christos 	  /* This symbol requires a procedure linkage table entry.  We
   1213      1.1  christos 	     actually build the entry in adjust_dynamic_symbol,
   1214      1.1  christos 	     because this might be a case of linking PIC code without
   1215      1.1  christos 	     linking in any dynamic objects, in which case we don't
   1216      1.1  christos 	     need to generate a procedure linkage table after all.  */
   1217      1.1  christos 	  if (h != NULL)
   1218      1.1  christos 	    {
   1219      1.1  christos 	      h->needs_plt = 1;
   1220      1.1  christos 	      if (h->plt.refcount < 0)
   1221      1.1  christos 		h->plt.refcount = 0;
   1222      1.1  christos 	      h->plt.refcount++;
   1223      1.1  christos 	    }
   1224      1.1  christos 	  break;
   1225      1.1  christos 
   1226      1.1  christos 	case R_LARCH_TLS_DTPREL32:
   1227      1.1  christos 	case R_LARCH_TLS_DTPREL64:
   1228      1.1  christos 	  need_dynreloc = 1;
   1229      1.1  christos 	  only_need_pcrel = 1;
   1230      1.1  christos 	  break;
   1231      1.1  christos 
   1232      1.1  christos 	case R_LARCH_32:
   1233  1.1.1.3  christos 	  if (ARCH_SIZE > 32
   1234  1.1.1.3  christos 	      && bfd_link_pic (info)
   1235  1.1.1.3  christos 	      && (sec->flags & SEC_ALLOC) != 0)
   1236  1.1.1.3  christos 	    {
   1237  1.1.1.3  christos 	      if (!is_abs_symbol)
   1238  1.1.1.3  christos 		{
   1239  1.1.1.3  christos 		  _bfd_error_handler
   1240  1.1.1.3  christos 		    (_("%pB: relocation R_LARCH_32 against non-absolute "
   1241  1.1.1.3  christos 		       "symbol `%s' cannot be used in ELFCLASS64 when "
   1242  1.1.1.3  christos 		       "making a shared object or PIE"),
   1243  1.1.1.3  christos 		     abfd, h ? h->root.root.string : "a local symbol");
   1244  1.1.1.3  christos 		  bfd_set_error (bfd_error_bad_value);
   1245  1.1.1.3  christos 		  return false;
   1246  1.1.1.3  christos 		}
   1247  1.1.1.3  christos 	    }
   1248  1.1.1.3  christos 
   1249  1.1.1.3  christos 	  /* Fall through.  */
   1250  1.1.1.3  christos 	case R_LARCH_JUMP_SLOT:
   1251      1.1  christos 	case R_LARCH_64:
   1252  1.1.1.2  christos 
   1253  1.1.1.3  christos 	  /* Resolved to const.  */
   1254  1.1.1.3  christos 	  if (is_abs_symbol)
   1255  1.1.1.3  christos 	    break;
   1256  1.1.1.3  christos 
   1257      1.1  christos 	  need_dynreloc = 1;
   1258      1.1  christos 
   1259      1.1  christos 	  /* If resolved symbol is defined in this object,
   1260      1.1  christos 	     1. Under pie, the symbol is known.  We convert it
   1261      1.1  christos 	     into R_LARCH_RELATIVE and need load-addr still.
   1262      1.1  christos 	     2. Under pde, the symbol is known and we can discard R_LARCH_NN.
   1263      1.1  christos 	     3. Under dll, R_LARCH_NN can't be changed normally, since
   1264      1.1  christos 	     its defination could be covered by the one in executable.
   1265      1.1  christos 	     For symbolic, we convert it into R_LARCH_RELATIVE.
   1266      1.1  christos 	     Thus, only under pde, it needs pcrel only.  We discard it.  */
   1267      1.1  christos 	  only_need_pcrel = bfd_link_pde (info);
   1268      1.1  christos 
   1269      1.1  christos 	  if (h != NULL
   1270      1.1  christos 	      && (!bfd_link_pic (info)
   1271      1.1  christos 		  || h->type == STT_GNU_IFUNC))
   1272      1.1  christos 	    {
   1273      1.1  christos 	      /* This reloc might not bind locally.  */
   1274      1.1  christos 	      h->non_got_ref = 1;
   1275      1.1  christos 	      h->pointer_equality_needed = 1;
   1276      1.1  christos 
   1277      1.1  christos 	      if (!h->def_regular
   1278      1.1  christos 		  || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
   1279      1.1  christos 		{
   1280      1.1  christos 		  /* We may need a .plt entry if the symbol is a function
   1281      1.1  christos 		     defined in a shared lib or is a function referenced
   1282      1.1  christos 		     from the code or read-only section.  */
   1283      1.1  christos 		  h->plt.refcount += 1;
   1284      1.1  christos 		}
   1285      1.1  christos 	    }
   1286      1.1  christos 	  break;
   1287      1.1  christos 
   1288      1.1  christos 	case R_LARCH_GNU_VTINHERIT:
   1289      1.1  christos 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
   1290      1.1  christos 	    return false;
   1291      1.1  christos 	  break;
   1292      1.1  christos 
   1293      1.1  christos 	case R_LARCH_GNU_VTENTRY:
   1294      1.1  christos 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
   1295      1.1  christos 	    return false;
   1296      1.1  christos 	  break;
   1297      1.1  christos 
   1298  1.1.1.3  christos 	case R_LARCH_ALIGN:
   1299  1.1.1.3  christos 	  /* Check against irrational R_LARCH_ALIGN relocs which may cause
   1300  1.1.1.3  christos 	     removing an odd number of bytes and disrupt DT_RELR.  */
   1301  1.1.1.3  christos 	  if (rel->r_offset % 4 != 0)
   1302  1.1.1.3  christos 	    {
   1303  1.1.1.3  christos 	      /* xgettext:c-format */
   1304  1.1.1.3  christos 	      _bfd_error_handler (
   1305  1.1.1.3  christos 		_("%pB: R_LARCH_ALIGN with offset %" PRId64 " not aligned "
   1306  1.1.1.3  christos 		  "to instruction boundary"),
   1307  1.1.1.3  christos 		abfd, (uint64_t) rel->r_offset);
   1308  1.1.1.3  christos 	      return false;
   1309  1.1.1.3  christos 	    }
   1310  1.1.1.3  christos 	  break;
   1311  1.1.1.3  christos 
   1312      1.1  christos 	default:
   1313      1.1  christos 	  break;
   1314      1.1  christos 	}
   1315      1.1  christos 
   1316      1.1  christos       /* Record some info for sizing and allocating dynamic entry.  */
   1317      1.1  christos       if (need_dynreloc && (sec->flags & SEC_ALLOC))
   1318      1.1  christos 	{
   1319      1.1  christos 	  /* When creating a shared object, we must copy these
   1320      1.1  christos 	     relocs into the output file.  We create a reloc
   1321      1.1  christos 	     section in dynobj and make room for the reloc.  */
   1322      1.1  christos 	  struct elf_dyn_relocs *p;
   1323      1.1  christos 	  struct elf_dyn_relocs **head;
   1324      1.1  christos 
   1325      1.1  christos 	  if (sreloc == NULL)
   1326      1.1  christos 	    {
   1327      1.1  christos 	      sreloc
   1328      1.1  christos 		= _bfd_elf_make_dynamic_reloc_section (sec, htab->elf.dynobj,
   1329      1.1  christos 						       LARCH_ELF_LOG_WORD_BYTES,
   1330      1.1  christos 						       abfd, /*rela?*/ true);
   1331      1.1  christos 	      if (sreloc == NULL)
   1332      1.1  christos 		return false;
   1333      1.1  christos 	    }
   1334      1.1  christos 
   1335      1.1  christos 	  /* If this is a global symbol, we count the number of
   1336      1.1  christos 	     relocations we need for this symbol.  */
   1337      1.1  christos 	  if (h != NULL)
   1338      1.1  christos 	    head = &h->dyn_relocs;
   1339      1.1  christos 	  else
   1340      1.1  christos 	    {
   1341      1.1  christos 	      /* Track dynamic relocs needed for local syms too.
   1342      1.1  christos 		 We really need local syms available to do this
   1343      1.1  christos 		 easily.  Oh well.  */
   1344      1.1  christos 
   1345      1.1  christos 	      asection *s;
   1346      1.1  christos 	      void *vpp;
   1347      1.1  christos 
   1348      1.1  christos 	      s = bfd_section_from_elf_index (abfd, isym->st_shndx);
   1349      1.1  christos 	      if (s == NULL)
   1350      1.1  christos 		s = sec;
   1351      1.1  christos 
   1352      1.1  christos 	      vpp = &elf_section_data (s)->local_dynrel;
   1353      1.1  christos 	      head = (struct elf_dyn_relocs **) vpp;
   1354      1.1  christos 	    }
   1355      1.1  christos 
   1356      1.1  christos 	  p = *head;
   1357      1.1  christos 	  if (p == NULL || p->sec != sec)
   1358      1.1  christos 	    {
   1359      1.1  christos 	      bfd_size_type amt = sizeof *p;
   1360      1.1  christos 	      p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt);
   1361      1.1  christos 	      if (p == NULL)
   1362      1.1  christos 		return false;
   1363      1.1  christos 	      p->next = *head;
   1364      1.1  christos 	      *head = p;
   1365      1.1  christos 	      p->sec = sec;
   1366      1.1  christos 	      p->count = 0;
   1367      1.1  christos 	      p->pc_count = 0;
   1368      1.1  christos 	    }
   1369      1.1  christos 
   1370      1.1  christos 	  p->count++;
   1371      1.1  christos 	  p->pc_count += only_need_pcrel;
   1372      1.1  christos 	}
   1373      1.1  christos     }
   1374      1.1  christos 
   1375      1.1  christos   return true;
   1376      1.1  christos }
   1377      1.1  christos 
   1378      1.1  christos /* Find dynamic relocs for H that apply to read-only sections.  */
   1379      1.1  christos 
   1380      1.1  christos static asection *
   1381      1.1  christos readonly_dynrelocs (struct elf_link_hash_entry *h)
   1382      1.1  christos {
   1383      1.1  christos   struct elf_dyn_relocs *p;
   1384      1.1  christos 
   1385      1.1  christos   for (p = h->dyn_relocs; p != NULL; p = p->next)
   1386      1.1  christos     {
   1387      1.1  christos       asection *s = p->sec->output_section;
   1388      1.1  christos 
   1389      1.1  christos       if (s != NULL && (s->flags & SEC_READONLY) != 0)
   1390      1.1  christos 	return p->sec;
   1391      1.1  christos     }
   1392      1.1  christos   return NULL;
   1393      1.1  christos }
   1394      1.1  christos 
   1395      1.1  christos /* Adjust a symbol defined by a dynamic object and referenced by a
   1396      1.1  christos    regular object.  The current definition is in some section of the
   1397      1.1  christos    dynamic object, but we're not including those sections.  We have to
   1398      1.1  christos    change the definition to something the rest of the link can
   1399      1.1  christos    understand.  */
   1400      1.1  christos static bool
   1401      1.1  christos loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   1402      1.1  christos 				     struct elf_link_hash_entry *h)
   1403      1.1  christos {
   1404      1.1  christos   struct loongarch_elf_link_hash_table *htab;
   1405      1.1  christos   bfd *dynobj;
   1406      1.1  christos 
   1407      1.1  christos   htab = loongarch_elf_hash_table (info);
   1408      1.1  christos   BFD_ASSERT (htab != NULL);
   1409      1.1  christos 
   1410      1.1  christos   dynobj = htab->elf.dynobj;
   1411      1.1  christos 
   1412      1.1  christos   /* Make sure we know what is going on here.  */
   1413      1.1  christos   BFD_ASSERT (dynobj != NULL
   1414  1.1.1.2  christos 	      && (h->needs_plt
   1415  1.1.1.2  christos 		  || h->type == STT_GNU_IFUNC
   1416  1.1.1.2  christos 		  || h->is_weakalias
   1417  1.1.1.2  christos 		  || (h->def_dynamic
   1418  1.1.1.2  christos 		      && h->ref_regular
   1419  1.1.1.2  christos 		      && !h->def_regular)));
   1420      1.1  christos 
   1421      1.1  christos   /* If this is a function, put it in the procedure linkage table.  We
   1422      1.1  christos      will fill in the contents of the procedure linkage table later
   1423      1.1  christos      (although we could actually do it here).  */
   1424      1.1  christos   if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
   1425      1.1  christos     {
   1426  1.1.1.2  christos       if (h->plt.refcount <= 0
   1427      1.1  christos 	  || (h->type != STT_GNU_IFUNC
   1428  1.1.1.3  christos 	      && (LARCH_REF_LOCAL (info, h)
   1429      1.1  christos 		  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
   1430      1.1  christos 		      && h->root.type == bfd_link_hash_undefweak))))
   1431      1.1  christos 	{
   1432      1.1  christos 	  /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
   1433      1.1  christos 	     in an input file, but the symbol was never referred to by a
   1434      1.1  christos 	     dynamic object, or if all references were garbage collected.
   1435      1.1  christos 	     In such a case, we don't actually need to build a PLT entry.  */
   1436      1.1  christos 	  h->plt.offset = MINUS_ONE;
   1437      1.1  christos 	  h->needs_plt = 0;
   1438      1.1  christos 	}
   1439      1.1  christos 
   1440      1.1  christos       return true;
   1441      1.1  christos     }
   1442      1.1  christos   else
   1443      1.1  christos     h->plt.offset = MINUS_ONE;
   1444      1.1  christos 
   1445      1.1  christos   /* If this is a weak symbol, and there is a real definition, the
   1446      1.1  christos      processor independent code will have arranged for us to see the
   1447      1.1  christos      real definition first, and we can just use the same value.  */
   1448      1.1  christos   if (h->is_weakalias)
   1449      1.1  christos     {
   1450      1.1  christos       struct elf_link_hash_entry *def = weakdef (h);
   1451      1.1  christos       BFD_ASSERT (def->root.type == bfd_link_hash_defined);
   1452      1.1  christos       h->root.u.def.section = def->root.u.def.section;
   1453      1.1  christos       h->root.u.def.value = def->root.u.def.value;
   1454      1.1  christos       return true;
   1455      1.1  christos     }
   1456      1.1  christos 
   1457  1.1.1.2  christos   /* R_LARCH_COPY is not adept glibc, not to generate.  */
   1458  1.1.1.2  christos   /* Can not print anything, because make check ld.  */
   1459  1.1.1.2  christos   return true;
   1460      1.1  christos }
   1461      1.1  christos 
   1462      1.1  christos /* Allocate space in .plt, .got and associated reloc sections for
   1463      1.1  christos    dynamic relocs.  */
   1464      1.1  christos 
   1465      1.1  christos static bool
   1466      1.1  christos allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   1467      1.1  christos {
   1468      1.1  christos   struct bfd_link_info *info;
   1469      1.1  christos   struct loongarch_elf_link_hash_table *htab;
   1470      1.1  christos   struct elf_dyn_relocs *p;
   1471      1.1  christos 
   1472      1.1  christos   if (h->root.type == bfd_link_hash_indirect)
   1473      1.1  christos     return true;
   1474      1.1  christos 
   1475      1.1  christos   if (h->type == STT_GNU_IFUNC
   1476      1.1  christos       && h->def_regular)
   1477      1.1  christos     return true;
   1478      1.1  christos 
   1479      1.1  christos   info = (struct bfd_link_info *) inf;
   1480      1.1  christos   htab = loongarch_elf_hash_table (info);
   1481  1.1.1.2  christos   bool dyn = htab->elf.dynamic_sections_created;
   1482      1.1  christos   BFD_ASSERT (htab != NULL);
   1483      1.1  christos 
   1484      1.1  christos   do
   1485      1.1  christos     {
   1486      1.1  christos       asection *plt, *gotplt, *relplt;
   1487      1.1  christos 
   1488      1.1  christos       if (!h->needs_plt)
   1489      1.1  christos 	break;
   1490      1.1  christos 
   1491      1.1  christos       h->needs_plt = 0;
   1492      1.1  christos 
   1493      1.1  christos       if (htab->elf.splt)
   1494      1.1  christos 	{
   1495  1.1.1.2  christos 	  if (h->dynindx == -1 && !h->forced_local && dyn
   1496  1.1.1.2  christos 	      && h->root.type == bfd_link_hash_undefweak)
   1497  1.1.1.2  christos 	    {
   1498  1.1.1.2  christos 	      if (!bfd_elf_link_record_dynamic_symbol (info, h))
   1499  1.1.1.2  christos 		return false;
   1500  1.1.1.2  christos 	    }
   1501      1.1  christos 
   1502      1.1  christos 	  if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
   1503      1.1  christos 	      && h->type != STT_GNU_IFUNC)
   1504      1.1  christos 	    break;
   1505      1.1  christos 
   1506      1.1  christos 	  plt = htab->elf.splt;
   1507      1.1  christos 	  gotplt = htab->elf.sgotplt;
   1508      1.1  christos 	  relplt = htab->elf.srelplt;
   1509      1.1  christos 	}
   1510      1.1  christos       else if (htab->elf.iplt)
   1511      1.1  christos 	{
   1512      1.1  christos 	  /* .iplt only for IFUNC.  */
   1513      1.1  christos 	  if (h->type != STT_GNU_IFUNC)
   1514      1.1  christos 	    break;
   1515      1.1  christos 
   1516      1.1  christos 	  plt = htab->elf.iplt;
   1517      1.1  christos 	  gotplt = htab->elf.igotplt;
   1518      1.1  christos 	  relplt = htab->elf.irelplt;
   1519      1.1  christos 	}
   1520      1.1  christos       else
   1521      1.1  christos 	break;
   1522      1.1  christos 
   1523      1.1  christos       if (plt->size == 0)
   1524      1.1  christos 	plt->size = PLT_HEADER_SIZE;
   1525      1.1  christos 
   1526      1.1  christos       h->plt.offset = plt->size;
   1527      1.1  christos       plt->size += PLT_ENTRY_SIZE;
   1528      1.1  christos       gotplt->size += GOT_ENTRY_SIZE;
   1529      1.1  christos       relplt->size += sizeof (ElfNN_External_Rela);
   1530      1.1  christos 
   1531      1.1  christos       /* If this symbol is not defined in a regular file, and we are
   1532      1.1  christos 	 not generating a shared library, then set the symbol to this
   1533      1.1  christos 	 location in the .plt.  This is required to make function
   1534      1.1  christos 	 pointers compare as equal between the normal executable and
   1535      1.1  christos 	 the shared library.  */
   1536  1.1.1.2  christos       if (!bfd_link_pic (info)
   1537      1.1  christos 	  && !h->def_regular)
   1538      1.1  christos 	{
   1539      1.1  christos 	  h->root.u.def.section = plt;
   1540      1.1  christos 	  h->root.u.def.value = h->plt.offset;
   1541      1.1  christos 	}
   1542      1.1  christos 
   1543      1.1  christos       h->needs_plt = 1;
   1544      1.1  christos     }
   1545      1.1  christos   while (0);
   1546      1.1  christos 
   1547      1.1  christos   if (!h->needs_plt)
   1548      1.1  christos     h->plt.offset = MINUS_ONE;
   1549      1.1  christos 
   1550      1.1  christos   if (0 < h->got.refcount)
   1551      1.1  christos     {
   1552      1.1  christos       asection *s;
   1553      1.1  christos       int tls_type = loongarch_elf_hash_entry (h)->tls_type;
   1554      1.1  christos 
   1555      1.1  christos       /* Make sure this symbol is output as a dynamic symbol.
   1556      1.1  christos 	 Undefined weak syms won't yet be marked as dynamic.  */
   1557  1.1.1.2  christos       if (h->dynindx == -1 && !h->forced_local && dyn
   1558  1.1.1.2  christos 	  && h->root.type == bfd_link_hash_undefweak)
   1559      1.1  christos 	{
   1560  1.1.1.2  christos 	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
   1561  1.1.1.2  christos 	    return false;
   1562      1.1  christos 	}
   1563      1.1  christos 
   1564      1.1  christos       s = htab->elf.sgot;
   1565      1.1  christos       h->got.offset = s->size;
   1566  1.1.1.2  christos       if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
   1567      1.1  christos 	{
   1568  1.1.1.3  christos 	  int indx = 0;
   1569  1.1.1.3  christos 	  bool need_reloc = false;
   1570  1.1.1.3  christos 	  LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, dyn, h, indx,
   1571  1.1.1.3  christos 					need_reloc);
   1572      1.1  christos 	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
   1573      1.1  christos 	  if (tls_type & GOT_TLS_GD)
   1574      1.1  christos 	    {
   1575      1.1  christos 	      s->size += 2 * GOT_ENTRY_SIZE;
   1576  1.1.1.3  christos 	      if (need_reloc)
   1577  1.1.1.3  christos 		htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
   1578      1.1  christos 	    }
   1579      1.1  christos 
   1580      1.1  christos 	  /* TLS_IE needs one dynamic reloc and one GOT slot.  */
   1581      1.1  christos 	  if (tls_type & GOT_TLS_IE)
   1582      1.1  christos 	    {
   1583      1.1  christos 	      s->size += GOT_ENTRY_SIZE;
   1584  1.1.1.3  christos 	      if (need_reloc)
   1585  1.1.1.3  christos 		htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
   1586  1.1.1.2  christos 	    }
   1587  1.1.1.2  christos 
   1588  1.1.1.2  christos 	  /* TLS_DESC needs one dynamic reloc and two GOT slot.  */
   1589  1.1.1.2  christos 	  if (tls_type & GOT_TLS_GDESC)
   1590  1.1.1.2  christos 	    {
   1591  1.1.1.2  christos 	      s->size += GOT_ENTRY_SIZE * 2;
   1592      1.1  christos 	      htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
   1593      1.1  christos 	    }
   1594      1.1  christos 	}
   1595  1.1.1.2  christos 
   1596      1.1  christos       else
   1597      1.1  christos 	{
   1598      1.1  christos 	  s->size += GOT_ENTRY_SIZE;
   1599  1.1.1.2  christos 	  if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
   1600  1.1.1.2  christos 	       || h->root.type != bfd_link_hash_undefweak)
   1601  1.1.1.2  christos 	      && (bfd_link_pic (info)
   1602  1.1.1.2  christos 		  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
   1603  1.1.1.2  christos 						      h))
   1604  1.1.1.2  christos 	      && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
   1605  1.1.1.2  christos 	      /* Undefined weak symbol in static PIE resolves to 0 without
   1606  1.1.1.2  christos 		 any dynamic relocations.  */
   1607      1.1  christos 	    htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
   1608      1.1  christos 	}
   1609      1.1  christos     }
   1610      1.1  christos   else
   1611      1.1  christos     h->got.offset = MINUS_ONE;
   1612      1.1  christos 
   1613      1.1  christos   if (h->dyn_relocs == NULL)
   1614      1.1  christos     return true;
   1615      1.1  christos 
   1616  1.1.1.2  christos   /* Extra dynamic relocate,
   1617  1.1.1.2  christos    * R_LARCH_64
   1618  1.1.1.2  christos    * R_LARCH_TLS_DTPRELNN
   1619  1.1.1.2  christos    * R_LARCH_JUMP_SLOT
   1620  1.1.1.2  christos    * R_LARCH_NN.  */
   1621  1.1.1.2  christos 
   1622  1.1.1.2  christos   if (SYMBOL_CALLS_LOCAL (info, h))
   1623      1.1  christos     {
   1624      1.1  christos       struct elf_dyn_relocs **pp;
   1625      1.1  christos 
   1626      1.1  christos       for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
   1627      1.1  christos 	{
   1628      1.1  christos 	  p->count -= p->pc_count;
   1629      1.1  christos 	  p->pc_count = 0;
   1630      1.1  christos 	  if (p->count == 0)
   1631      1.1  christos 	    *pp = p->next;
   1632      1.1  christos 	  else
   1633      1.1  christos 	    pp = &p->next;
   1634      1.1  christos 	}
   1635      1.1  christos     }
   1636      1.1  christos 
   1637      1.1  christos   if (h->root.type == bfd_link_hash_undefweak)
   1638      1.1  christos     {
   1639  1.1.1.2  christos       if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
   1640  1.1.1.2  christos 	  || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
   1641  1.1.1.2  christos 	  || (!bfd_link_pic (info) && h->non_got_ref))
   1642      1.1  christos 	h->dyn_relocs = NULL;
   1643  1.1.1.2  christos       else if (h->dynindx == -1 && !h->forced_local)
   1644  1.1.1.2  christos 	{
   1645  1.1.1.2  christos 	  /* Make sure this symbol is output as a dynamic symbol.
   1646  1.1.1.2  christos 	     Undefined weak syms won't yet be marked as dynamic.  */
   1647  1.1.1.2  christos 	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
   1648  1.1.1.2  christos 	    return false;
   1649  1.1.1.2  christos 
   1650  1.1.1.2  christos 	  if (h->dynindx == -1)
   1651  1.1.1.2  christos 	    h->dyn_relocs = NULL;
   1652  1.1.1.2  christos 	}
   1653      1.1  christos     }
   1654      1.1  christos 
   1655      1.1  christos   for (p = h->dyn_relocs; p != NULL; p = p->next)
   1656      1.1  christos     {
   1657  1.1.1.3  christos       if (discarded_section (p->sec))
   1658  1.1.1.3  christos 	continue;
   1659      1.1  christos       asection *sreloc = elf_section_data (p->sec)->sreloc;
   1660      1.1  christos       sreloc->size += p->count * sizeof (ElfNN_External_Rela);
   1661      1.1  christos     }
   1662      1.1  christos 
   1663      1.1  christos   return true;
   1664      1.1  christos }
   1665      1.1  christos 
   1666  1.1.1.2  christos /* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
   1667  1.1.1.2  christos    For local def and ref ifunc,
   1668  1.1.1.2  christos    dynamic relocations are stored in
   1669  1.1.1.2  christos    1.  rela.srelgot section in dynamic object (dll or exec).
   1670  1.1.1.2  christos    2.  rela.irelplt section in static executable.
   1671  1.1.1.2  christos    Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
   1672  1.1.1.2  christos    instead of rela.srelplt.  Glibc ELF loader will not support
   1673  1.1.1.2  christos    R_LARCH_IRELATIVE relocation in rela.plt.  */
   1674  1.1.1.2  christos 
   1675  1.1.1.2  christos static bool
   1676  1.1.1.2  christos local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
   1677  1.1.1.2  christos 				    struct elf_link_hash_entry *h,
   1678  1.1.1.2  christos 				    struct elf_dyn_relocs **head,
   1679  1.1.1.2  christos 				    unsigned int plt_entry_size,
   1680  1.1.1.2  christos 				    unsigned int plt_header_size,
   1681  1.1.1.2  christos 				    unsigned int got_entry_size,
   1682  1.1.1.2  christos 				    bool avoid_plt)
   1683  1.1.1.2  christos {
   1684  1.1.1.2  christos   asection *plt, *gotplt, *relplt;
   1685  1.1.1.2  christos   struct elf_dyn_relocs *p;
   1686  1.1.1.2  christos   unsigned int sizeof_reloc;
   1687  1.1.1.2  christos   const struct elf_backend_data *bed;
   1688  1.1.1.2  christos   struct elf_link_hash_table *htab;
   1689  1.1.1.2  christos   /* If AVOID_PLT is TRUE, don't use PLT if possible.  */
   1690  1.1.1.2  christos   bool use_plt = !avoid_plt || h->plt.refcount > 0;
   1691  1.1.1.2  christos   bool need_dynreloc = !use_plt || bfd_link_pic (info);
   1692  1.1.1.2  christos 
   1693  1.1.1.2  christos   /* When a PIC object references a STT_GNU_IFUNC symbol defined
   1694  1.1.1.2  christos      in executable or it isn't referenced via PLT, the address of
   1695  1.1.1.2  christos      the resolved function may be used.  But in non-PIC executable,
   1696  1.1.1.2  christos      the address of its plt slot may be used.  Pointer equality may
   1697  1.1.1.2  christos      not work correctly.  PIE or non-PLT reference should be used if
   1698  1.1.1.2  christos      pointer equality is required here.
   1699  1.1.1.2  christos 
   1700  1.1.1.2  christos      If STT_GNU_IFUNC symbol is defined in position-dependent executable,
   1701  1.1.1.2  christos      backend should change it to the normal function and set its address
   1702  1.1.1.2  christos      to its PLT entry which should be resolved by R_*_IRELATIVE at
   1703  1.1.1.2  christos      run-time.  All external references should be resolved to its PLT in
   1704  1.1.1.2  christos      executable.  */
   1705  1.1.1.2  christos   if (!need_dynreloc
   1706  1.1.1.2  christos       && !(bfd_link_pde (info) && h->def_regular)
   1707  1.1.1.2  christos       && (h->dynindx != -1
   1708  1.1.1.2  christos 	  || info->export_dynamic)
   1709  1.1.1.2  christos       && h->pointer_equality_needed)
   1710  1.1.1.2  christos     {
   1711  1.1.1.3  christos       info->callbacks->fatal
   1712  1.1.1.2  christos 	/* xgettext:c-format.  */
   1713  1.1.1.3  christos 	(_("%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
   1714  1.1.1.2  christos 	   "equality in `%pB' can not be used when making an "
   1715  1.1.1.2  christos 	   "executable; recompile with -fPIE and relink with -pie\n"),
   1716  1.1.1.2  christos 	 h->root.root.string,
   1717  1.1.1.2  christos 	 h->root.u.def.section->owner);
   1718  1.1.1.2  christos       bfd_set_error (bfd_error_bad_value);
   1719  1.1.1.2  christos       return false;
   1720  1.1.1.2  christos     }
   1721  1.1.1.2  christos 
   1722  1.1.1.2  christos   htab = elf_hash_table (info);
   1723  1.1.1.2  christos 
   1724  1.1.1.2  christos   /* When the symbol is marked with regular reference, if PLT isn't used
   1725  1.1.1.2  christos      or we are building a PIC object, we must keep dynamic relocation
   1726  1.1.1.2  christos      if there is non-GOT reference and use PLT if there is PC-relative
   1727  1.1.1.2  christos      reference.  */
   1728  1.1.1.2  christos   if (need_dynreloc && h->ref_regular)
   1729  1.1.1.2  christos     {
   1730  1.1.1.2  christos       bool keep = false;
   1731  1.1.1.2  christos       for (p = *head; p != NULL; p = p->next)
   1732  1.1.1.2  christos 	if (p->count)
   1733  1.1.1.2  christos 	  {
   1734  1.1.1.2  christos 	    h->non_got_ref = 1;
   1735  1.1.1.2  christos 	    /* Need dynamic relocations for non-GOT reference.  */
   1736  1.1.1.2  christos 	    keep = true;
   1737  1.1.1.2  christos 	    if (p->pc_count)
   1738  1.1.1.2  christos 	      {
   1739  1.1.1.2  christos 		/* Must use PLT for PC-relative reference.  */
   1740  1.1.1.2  christos 		use_plt = true;
   1741  1.1.1.2  christos 		need_dynreloc = bfd_link_pic (info);
   1742  1.1.1.2  christos 		break;
   1743  1.1.1.2  christos 	      }
   1744  1.1.1.2  christos 	  }
   1745  1.1.1.2  christos       if (keep)
   1746  1.1.1.2  christos 	goto keep;
   1747  1.1.1.2  christos     }
   1748  1.1.1.2  christos 
   1749  1.1.1.2  christos   /* Support garbage collection against STT_GNU_IFUNC symbols.  */
   1750  1.1.1.2  christos   if (h->plt.refcount <= 0 && h->got.refcount <= 0)
   1751  1.1.1.2  christos     {
   1752  1.1.1.2  christos       h->got = htab->init_got_offset;
   1753  1.1.1.2  christos       h->plt = htab->init_plt_offset;
   1754  1.1.1.2  christos       *head = NULL;
   1755  1.1.1.2  christos       return true;
   1756  1.1.1.2  christos     }
   1757  1.1.1.2  christos 
   1758  1.1.1.2  christos   /* Return and discard space for dynamic relocations against it if
   1759  1.1.1.2  christos      it is never referenced.  */
   1760  1.1.1.2  christos   if (!h->ref_regular)
   1761  1.1.1.2  christos     {
   1762  1.1.1.2  christos       if (h->plt.refcount > 0
   1763  1.1.1.2  christos 	  || h->got.refcount > 0)
   1764  1.1.1.2  christos 	abort ();
   1765  1.1.1.2  christos       h->got = htab->init_got_offset;
   1766  1.1.1.2  christos       h->plt = htab->init_plt_offset;
   1767  1.1.1.2  christos       *head = NULL;
   1768  1.1.1.2  christos       return true;
   1769  1.1.1.2  christos     }
   1770  1.1.1.2  christos 
   1771  1.1.1.2  christos  keep:
   1772  1.1.1.2  christos   bed = get_elf_backend_data (info->output_bfd);
   1773  1.1.1.2  christos   if (bed->rela_plts_and_copies_p)
   1774  1.1.1.2  christos     sizeof_reloc = bed->s->sizeof_rela;
   1775  1.1.1.2  christos   else
   1776  1.1.1.2  christos     sizeof_reloc = bed->s->sizeof_rel;
   1777  1.1.1.2  christos 
   1778  1.1.1.2  christos   /* When building a static executable, use iplt, igot.plt and
   1779  1.1.1.2  christos      rela.iplt sections for STT_GNU_IFUNC symbols.  */
   1780  1.1.1.2  christos   if (htab->splt != NULL)
   1781  1.1.1.2  christos     {
   1782  1.1.1.2  christos       plt = htab->splt;
   1783  1.1.1.2  christos       gotplt = htab->sgotplt;
   1784  1.1.1.2  christos       /* Change dynamic info of ifunc gotplt from srelplt to srelgot.  */
   1785  1.1.1.2  christos       relplt = htab->srelgot;
   1786  1.1.1.2  christos 
   1787  1.1.1.2  christos       /* If this is the first plt entry and PLT is used, make room for
   1788  1.1.1.2  christos 	 the special first entry.  */
   1789  1.1.1.2  christos       if (plt->size == 0 && use_plt)
   1790  1.1.1.2  christos 	plt->size += plt_header_size;
   1791  1.1.1.2  christos     }
   1792  1.1.1.2  christos   else
   1793  1.1.1.2  christos     {
   1794  1.1.1.2  christos       plt = htab->iplt;
   1795  1.1.1.2  christos       gotplt = htab->igotplt;
   1796  1.1.1.2  christos       relplt = htab->irelplt;
   1797  1.1.1.2  christos     }
   1798  1.1.1.2  christos 
   1799  1.1.1.2  christos   if (use_plt)
   1800  1.1.1.2  christos     {
   1801  1.1.1.2  christos       /* Don't update value of STT_GNU_IFUNC symbol to PLT.  We need
   1802  1.1.1.2  christos 	 the original value for R_*_IRELATIVE.  */
   1803  1.1.1.2  christos       h->plt.offset = plt->size;
   1804  1.1.1.2  christos 
   1805  1.1.1.2  christos       /* Make room for this entry in the plt/iplt section.  */
   1806  1.1.1.2  christos       plt->size += plt_entry_size;
   1807  1.1.1.2  christos 
   1808  1.1.1.2  christos       /* We also need to make an entry in the got.plt/got.iplt section,
   1809  1.1.1.2  christos 	 which will be placed in the got section by the linker script.  */
   1810  1.1.1.2  christos       gotplt->size += got_entry_size;
   1811  1.1.1.2  christos     }
   1812  1.1.1.2  christos 
   1813  1.1.1.2  christos   /* We also need to make an entry in the rela.plt/.rela.iplt
   1814  1.1.1.2  christos      section for GOTPLT relocation if PLT is used.  */
   1815  1.1.1.2  christos   if (use_plt)
   1816  1.1.1.2  christos     {
   1817  1.1.1.2  christos       relplt->size += sizeof_reloc;
   1818  1.1.1.2  christos       relplt->reloc_count++;
   1819  1.1.1.2  christos     }
   1820  1.1.1.2  christos 
   1821  1.1.1.2  christos   /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
   1822  1.1.1.2  christos      there is a non-GOT reference in a PIC object or PLT isn't used.  */
   1823  1.1.1.2  christos   if (!need_dynreloc || !h->non_got_ref)
   1824  1.1.1.2  christos     *head = NULL;
   1825  1.1.1.2  christos 
   1826  1.1.1.2  christos   /* Finally, allocate space.  */
   1827  1.1.1.2  christos   p = *head;
   1828  1.1.1.2  christos   if (p != NULL)
   1829  1.1.1.2  christos     {
   1830  1.1.1.2  christos       bfd_size_type count = 0;
   1831  1.1.1.2  christos       do
   1832  1.1.1.2  christos 	{
   1833  1.1.1.2  christos 	  count += p->count;
   1834  1.1.1.2  christos 	  p = p->next;
   1835  1.1.1.2  christos 	}
   1836  1.1.1.2  christos       while (p != NULL);
   1837  1.1.1.2  christos 
   1838  1.1.1.2  christos       htab->ifunc_resolvers = count != 0;
   1839  1.1.1.2  christos 
   1840  1.1.1.2  christos       /* Dynamic relocations are stored in
   1841  1.1.1.2  christos 	 1.  rela.srelgot section in PIC object.
   1842  1.1.1.2  christos 	 2.  rela.srelgot section in dynamic executable.
   1843  1.1.1.2  christos 	 3.  rela.irelplt section in static executable.  */
   1844  1.1.1.2  christos       if (htab->splt != NULL)
   1845  1.1.1.2  christos 	htab->srelgot->size += count * sizeof_reloc;
   1846  1.1.1.2  christos       else
   1847  1.1.1.2  christos 	{
   1848  1.1.1.2  christos 	  relplt->size += count * sizeof_reloc;
   1849  1.1.1.2  christos 	  relplt->reloc_count += count;
   1850  1.1.1.2  christos 	}
   1851  1.1.1.2  christos     }
   1852  1.1.1.2  christos 
   1853  1.1.1.2  christos   /* For STT_GNU_IFUNC symbol, got.plt has the real function address
   1854  1.1.1.2  christos      and got has the PLT entry adddress.  We will load the GOT entry
   1855  1.1.1.2  christos      with the PLT entry in finish_dynamic_symbol if it is used.  For
   1856  1.1.1.2  christos      branch, it uses got.plt.  For symbol value, if PLT is used,
   1857  1.1.1.2  christos      1.  Use got.plt in a PIC object if it is forced local or not
   1858  1.1.1.2  christos      dynamic.
   1859  1.1.1.2  christos      2.  Use got.plt in a non-PIC object if pointer equality isn't
   1860  1.1.1.2  christos      needed.
   1861  1.1.1.2  christos      3.  Use got.plt in PIE.
   1862  1.1.1.2  christos      4.  Use got.plt if got isn't used.
   1863  1.1.1.2  christos      5.  Otherwise use got so that it can be shared among different
   1864  1.1.1.2  christos      objects at run-time.
   1865  1.1.1.2  christos      If PLT isn't used, always use got for symbol value.
   1866  1.1.1.2  christos      We only need to relocate got entry in PIC object or in dynamic
   1867  1.1.1.2  christos      executable without PLT.  */
   1868  1.1.1.2  christos   if (use_plt
   1869  1.1.1.2  christos       && (h->got.refcount <= 0
   1870  1.1.1.2  christos 	  || (bfd_link_pic (info)
   1871  1.1.1.2  christos 	      && (h->dynindx == -1
   1872  1.1.1.2  christos 		  || h->forced_local))
   1873  1.1.1.2  christos 	  || (
   1874  1.1.1.2  christos 	      !h->pointer_equality_needed)
   1875  1.1.1.2  christos 	  || htab->sgot == NULL))
   1876  1.1.1.2  christos     {
   1877  1.1.1.2  christos       /* Use got.plt.  */
   1878  1.1.1.2  christos       h->got.offset = (bfd_vma) -1;
   1879  1.1.1.2  christos     }
   1880  1.1.1.2  christos   else
   1881  1.1.1.2  christos     {
   1882  1.1.1.2  christos       if (!use_plt)
   1883  1.1.1.2  christos 	{
   1884  1.1.1.2  christos 	  /* PLT isn't used.  */
   1885  1.1.1.2  christos 	  h->plt.offset = (bfd_vma) -1;
   1886  1.1.1.2  christos 	}
   1887  1.1.1.2  christos       if (h->got.refcount <= 0)
   1888  1.1.1.2  christos 	{
   1889  1.1.1.2  christos 	  /* GOT isn't need when there are only relocations for static
   1890  1.1.1.2  christos 	     pointers.  */
   1891  1.1.1.2  christos 	  h->got.offset = (bfd_vma) -1;
   1892  1.1.1.2  christos 	}
   1893  1.1.1.2  christos       else
   1894  1.1.1.2  christos 	{
   1895  1.1.1.2  christos 	  h->got.offset = htab->sgot->size;
   1896  1.1.1.2  christos 	  htab->sgot->size += got_entry_size;
   1897  1.1.1.2  christos 	  /* Need to relocate the GOT entry in a PIC object or PLT isn't
   1898  1.1.1.2  christos 	     used.  Otherwise, the GOT entry will be filled with the PLT
   1899  1.1.1.2  christos 	     entry and dynamic GOT relocation isn't needed.  */
   1900  1.1.1.2  christos 	  if (need_dynreloc)
   1901  1.1.1.2  christos 	    {
   1902  1.1.1.2  christos 	      /* For non-static executable, dynamic GOT relocation is in
   1903  1.1.1.2  christos 		 rela.got section, but for static executable, it is
   1904  1.1.1.2  christos 		 in rela.iplt section.  */
   1905  1.1.1.2  christos 	      if (htab->splt != NULL)
   1906  1.1.1.2  christos 		htab->srelgot->size += sizeof_reloc;
   1907  1.1.1.2  christos 	      else
   1908  1.1.1.2  christos 		{
   1909  1.1.1.2  christos 		  relplt->size += sizeof_reloc;
   1910  1.1.1.2  christos 		  relplt->reloc_count++;
   1911  1.1.1.2  christos 		}
   1912  1.1.1.2  christos 	    }
   1913  1.1.1.2  christos 	}
   1914  1.1.1.2  christos     }
   1915  1.1.1.2  christos 
   1916  1.1.1.2  christos   return true;
   1917  1.1.1.2  christos }
   1918  1.1.1.2  christos 
   1919      1.1  christos /* Allocate space in .plt, .got and associated reloc sections for
   1920      1.1  christos    ifunc dynamic relocs.  */
   1921      1.1  christos 
   1922      1.1  christos static bool
   1923  1.1.1.3  christos elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
   1924  1.1.1.3  christos 				struct bfd_link_info *info,
   1925  1.1.1.3  christos 				bool ref_local)
   1926      1.1  christos {
   1927      1.1  christos   /* An example of a bfd_link_hash_indirect symbol is versioned
   1928      1.1  christos      symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
   1929      1.1  christos      -> __gxx_personality_v0(bfd_link_hash_defined)
   1930      1.1  christos 
   1931      1.1  christos      There is no need to process bfd_link_hash_indirect symbols here
   1932      1.1  christos      because we will also be presented with the concrete instance of
   1933      1.1  christos      the symbol and loongarch_elf_copy_indirect_symbol () will have been
   1934      1.1  christos      called to copy all relevant data from the generic to the concrete
   1935      1.1  christos      symbol instance.  */
   1936      1.1  christos   if (h->root.type == bfd_link_hash_indirect)
   1937      1.1  christos     return true;
   1938      1.1  christos 
   1939      1.1  christos   if (h->root.type == bfd_link_hash_warning)
   1940      1.1  christos     h = (struct elf_link_hash_entry *) h->root.u.i.link;
   1941      1.1  christos 
   1942      1.1  christos   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
   1943      1.1  christos      here if it is defined and referenced in a non-shared object.  */
   1944  1.1.1.2  christos   if (h->type == STT_GNU_IFUNC && h->def_regular)
   1945  1.1.1.2  christos     {
   1946  1.1.1.3  christos       if (ref_local && LARCH_REF_LOCAL (info, h))
   1947  1.1.1.2  christos 	return local_allocate_ifunc_dyn_relocs (info, h,
   1948  1.1.1.2  christos 						&h->dyn_relocs,
   1949  1.1.1.2  christos 						PLT_ENTRY_SIZE,
   1950  1.1.1.2  christos 						PLT_HEADER_SIZE,
   1951  1.1.1.2  christos 						GOT_ENTRY_SIZE,
   1952  1.1.1.2  christos 						false);
   1953  1.1.1.3  christos       else if (!ref_local && !LARCH_REF_LOCAL (info, h))
   1954  1.1.1.2  christos 	return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
   1955  1.1.1.2  christos 						   &h->dyn_relocs,
   1956  1.1.1.2  christos 						   PLT_ENTRY_SIZE,
   1957  1.1.1.2  christos 						   PLT_HEADER_SIZE,
   1958  1.1.1.2  christos 						   GOT_ENTRY_SIZE,
   1959  1.1.1.2  christos 						   false);
   1960  1.1.1.2  christos     }
   1961  1.1.1.2  christos 
   1962      1.1  christos   return true;
   1963      1.1  christos }
   1964      1.1  christos 
   1965  1.1.1.3  christos static bool
   1966  1.1.1.3  christos elfNN_allocate_ifunc_dynrelocs_ref_local (struct elf_link_hash_entry *h,
   1967  1.1.1.3  christos 					  void *info)
   1968  1.1.1.3  christos {
   1969  1.1.1.3  christos   return elfNN_allocate_ifunc_dynrelocs (h, (struct bfd_link_info *) info,
   1970  1.1.1.3  christos 					 true);
   1971  1.1.1.3  christos }
   1972  1.1.1.3  christos 
   1973  1.1.1.3  christos static bool
   1974  1.1.1.3  christos elfNN_allocate_ifunc_dynrelocs_ref_global (struct elf_link_hash_entry *h,
   1975  1.1.1.3  christos 					   void *info)
   1976  1.1.1.3  christos {
   1977  1.1.1.3  christos   return elfNN_allocate_ifunc_dynrelocs (h, (struct bfd_link_info *) info,
   1978  1.1.1.3  christos 					 false);
   1979  1.1.1.3  christos }
   1980  1.1.1.3  christos 
   1981      1.1  christos /* Allocate space in .plt, .got and associated reloc sections for
   1982      1.1  christos    ifunc dynamic relocs.  */
   1983      1.1  christos 
   1984  1.1.1.2  christos static int
   1985  1.1.1.2  christos elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
   1986      1.1  christos {
   1987      1.1  christos   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
   1988      1.1  christos 
   1989      1.1  christos   if (h->type != STT_GNU_IFUNC
   1990      1.1  christos       || !h->def_regular
   1991      1.1  christos       || !h->ref_regular
   1992      1.1  christos       || !h->forced_local
   1993      1.1  christos       || h->root.type != bfd_link_hash_defined)
   1994      1.1  christos     abort ();
   1995      1.1  christos 
   1996  1.1.1.3  christos   return elfNN_allocate_ifunc_dynrelocs_ref_local (h, inf);
   1997      1.1  christos }
   1998      1.1  christos 
   1999      1.1  christos /* Set DF_TEXTREL if we find any dynamic relocs that apply to
   2000      1.1  christos    read-only sections.  */
   2001      1.1  christos 
   2002      1.1  christos static bool
   2003      1.1  christos maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
   2004      1.1  christos {
   2005      1.1  christos   asection *sec;
   2006      1.1  christos 
   2007      1.1  christos   if (h->root.type == bfd_link_hash_indirect)
   2008      1.1  christos     return true;
   2009      1.1  christos 
   2010      1.1  christos   sec = readonly_dynrelocs (h);
   2011      1.1  christos   if (sec != NULL)
   2012      1.1  christos     {
   2013      1.1  christos       struct bfd_link_info *info = (struct bfd_link_info *) info_p;
   2014      1.1  christos 
   2015      1.1  christos       info->flags |= DF_TEXTREL;
   2016      1.1  christos       info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' in "
   2017      1.1  christos 				"read-only section `%pA'\n"),
   2018      1.1  christos 			      sec->owner, h->root.root.string, sec);
   2019      1.1  christos 
   2020      1.1  christos       /* Not an error, just cut short the traversal.  */
   2021      1.1  christos       return false;
   2022      1.1  christos     }
   2023      1.1  christos   return true;
   2024      1.1  christos }
   2025      1.1  christos 
   2026      1.1  christos static bool
   2027  1.1.1.3  christos record_relr (struct loongarch_elf_link_hash_table *htab, asection *sec,
   2028  1.1.1.3  christos 	     bfd_vma off, asection *sreloc)
   2029  1.1.1.3  christos {
   2030  1.1.1.3  christos   struct relr_entry **sec_relr = &loongarch_elf_section_data (sec)->relr;
   2031  1.1.1.3  christos 
   2032  1.1.1.3  christos   /* Undo the relocation section size accounting.  */
   2033  1.1.1.3  christos   BFD_ASSERT (sreloc->size >= sizeof (ElfNN_External_Rela));
   2034  1.1.1.3  christos   sreloc->size -= sizeof (ElfNN_External_Rela);
   2035  1.1.1.3  christos 
   2036  1.1.1.3  christos   BFD_ASSERT (off % 2 == 0 && sec->alignment_power > 0);
   2037  1.1.1.3  christos   if (htab->relr_count >= htab->relr_alloc)
   2038  1.1.1.3  christos     {
   2039  1.1.1.3  christos       if (htab->relr_alloc == 0)
   2040  1.1.1.3  christos 	htab->relr_alloc = 4096;
   2041  1.1.1.3  christos       else
   2042  1.1.1.3  christos 	htab->relr_alloc *= 2;
   2043  1.1.1.3  christos 
   2044  1.1.1.3  christos       htab->relr = bfd_realloc (htab->relr,
   2045  1.1.1.3  christos 				htab->relr_alloc * sizeof (*htab->relr));
   2046  1.1.1.3  christos       if (!htab->relr)
   2047  1.1.1.3  christos 	return false;
   2048  1.1.1.3  christos     }
   2049  1.1.1.3  christos   htab->relr[htab->relr_count].sec = sec;
   2050  1.1.1.3  christos   htab->relr[htab->relr_count].off = off;
   2051  1.1.1.3  christos   if (*sec_relr == NULL)
   2052  1.1.1.3  christos     *sec_relr = &htab->relr[htab->relr_count];
   2053  1.1.1.3  christos   htab->relr_count++;
   2054  1.1.1.3  christos   return true;
   2055  1.1.1.3  christos }
   2056  1.1.1.3  christos 
   2057  1.1.1.3  christos static bool
   2058  1.1.1.3  christos record_relr_local_got_relocs (bfd *input_bfd, struct bfd_link_info *info)
   2059  1.1.1.3  christos {
   2060  1.1.1.3  christos   bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
   2061  1.1.1.3  christos   char *local_tls_type = _bfd_loongarch_elf_local_got_tls_type (input_bfd);
   2062  1.1.1.3  christos   Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
   2063  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab =
   2064  1.1.1.3  christos     loongarch_elf_hash_table (info);
   2065  1.1.1.3  christos 
   2066  1.1.1.3  christos   if (!local_got_offsets || !local_tls_type || !bfd_link_pic (info))
   2067  1.1.1.3  christos     return true;
   2068  1.1.1.3  christos 
   2069  1.1.1.3  christos   for (unsigned i = 0; i < symtab_hdr->sh_info; i++)
   2070  1.1.1.3  christos     {
   2071  1.1.1.3  christos       bfd_vma off = local_got_offsets[i];
   2072  1.1.1.3  christos 
   2073  1.1.1.3  christos       /* FIXME: If the local symbol is in SHN_ABS then emitting
   2074  1.1.1.3  christos 	 a relative relocation is not correct, but it seems to be wrong
   2075  1.1.1.3  christos 	 in loongarch_elf_relocate_section too.  */
   2076  1.1.1.3  christos       if (local_tls_type[i] == GOT_NORMAL
   2077  1.1.1.3  christos 	  && !record_relr (htab, htab->elf.sgot, off, htab->elf.srelgot))
   2078  1.1.1.3  christos 	return false;
   2079  1.1.1.3  christos     }
   2080  1.1.1.3  christos 
   2081  1.1.1.3  christos   return true;
   2082  1.1.1.3  christos }
   2083  1.1.1.3  christos 
   2084  1.1.1.3  christos static bool
   2085  1.1.1.3  christos record_relr_dyn_got_relocs (struct elf_link_hash_entry *h, void *inf)
   2086  1.1.1.3  christos {
   2087  1.1.1.3  christos   struct bfd_link_info *info = (struct bfd_link_info *) inf;
   2088  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab =
   2089  1.1.1.3  christos     loongarch_elf_hash_table (info);
   2090  1.1.1.3  christos 
   2091  1.1.1.3  christos   if (h->root.type == bfd_link_hash_indirect)
   2092  1.1.1.3  christos     return true;
   2093  1.1.1.3  christos   if (h->type == STT_GNU_IFUNC && h->def_regular)
   2094  1.1.1.3  christos     return true;
   2095  1.1.1.3  christos   if (h->got.refcount <= 0)
   2096  1.1.1.3  christos     return true;
   2097  1.1.1.3  christos   if (loongarch_elf_hash_entry (h)->tls_type
   2098  1.1.1.3  christos       & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
   2099  1.1.1.3  christos     return true;
   2100  1.1.1.3  christos   if (!bfd_link_pic (info))
   2101  1.1.1.3  christos     return true;
   2102  1.1.1.3  christos 
   2103  1.1.1.3  christos   /* On LoongArch a GOT entry for undefined weak symbol is never relocated
   2104  1.1.1.3  christos      with R_LARCH_RELATIVE: we don't have -z dynamic-undefined-weak, thus
   2105  1.1.1.3  christos      the GOT entry is either const 0 (if the symbol is LARCH_REF_LOCAL) or
   2106  1.1.1.3  christos      relocated with R_LARCH_NN (otherwise).  */
   2107  1.1.1.3  christos   if (h->root.type == bfd_link_hash_undefweak)
   2108  1.1.1.3  christos     return true;
   2109  1.1.1.3  christos 
   2110  1.1.1.3  christos   if (!LARCH_REF_LOCAL (info, h))
   2111  1.1.1.3  christos     return true;
   2112  1.1.1.3  christos   if (bfd_is_abs_symbol (&h->root))
   2113  1.1.1.3  christos     return true;
   2114  1.1.1.3  christos 
   2115  1.1.1.3  christos   if (!record_relr (htab, htab->elf.sgot, h->got.offset,
   2116  1.1.1.3  christos 		    htab->elf.srelgot))
   2117  1.1.1.3  christos     return false;
   2118  1.1.1.3  christos 
   2119  1.1.1.3  christos   return true;
   2120  1.1.1.3  christos }
   2121  1.1.1.3  christos 
   2122  1.1.1.3  christos static bool
   2123  1.1.1.3  christos record_relr_non_got_relocs (bfd *input_bfd, struct bfd_link_info *info,
   2124  1.1.1.3  christos 			    asection *sec)
   2125  1.1.1.3  christos {
   2126  1.1.1.3  christos   asection *sreloc;
   2127  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab;
   2128  1.1.1.3  christos   Elf_Internal_Rela *relocs, *rel, *rel_end;
   2129  1.1.1.3  christos   Elf_Internal_Shdr *symtab_hdr;
   2130  1.1.1.3  christos   struct elf_link_hash_entry **sym_hashes;
   2131  1.1.1.3  christos 
   2132  1.1.1.3  christos   if (!bfd_link_pic (info))
   2133  1.1.1.3  christos     return true;
   2134  1.1.1.3  christos   if (sec->reloc_count == 0)
   2135  1.1.1.3  christos     return true;
   2136  1.1.1.3  christos   if ((sec->flags & (SEC_RELOC | SEC_ALLOC | SEC_DEBUGGING))
   2137  1.1.1.3  christos        != (SEC_RELOC | SEC_ALLOC))
   2138  1.1.1.3  christos     return true;
   2139  1.1.1.3  christos   if (sec->alignment_power == 0)
   2140  1.1.1.3  christos     return true;
   2141  1.1.1.3  christos   if (discarded_section (sec))
   2142  1.1.1.3  christos     return true;
   2143  1.1.1.3  christos 
   2144  1.1.1.3  christos   sreloc = elf_section_data (sec)->sreloc;
   2145  1.1.1.3  christos   if (sreloc == NULL)
   2146  1.1.1.3  christos     return true;
   2147  1.1.1.3  christos 
   2148  1.1.1.3  christos   htab = loongarch_elf_hash_table (info);
   2149  1.1.1.3  christos   symtab_hdr = &elf_symtab_hdr (input_bfd);
   2150  1.1.1.3  christos   sym_hashes = elf_sym_hashes (input_bfd);
   2151  1.1.1.3  christos   relocs = _bfd_elf_link_info_read_relocs (input_bfd, info, sec, NULL,
   2152  1.1.1.3  christos 					   NULL, info->keep_memory);
   2153  1.1.1.3  christos   BFD_ASSERT (relocs != NULL);
   2154  1.1.1.3  christos   rel_end = relocs + sec->reloc_count;
   2155  1.1.1.3  christos   for (rel = relocs; rel < rel_end; rel++)
   2156  1.1.1.3  christos     {
   2157  1.1.1.3  christos       unsigned r_symndx = ELFNN_R_SYM (rel->r_info);
   2158  1.1.1.3  christos       unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
   2159  1.1.1.3  christos       struct elf_link_hash_entry *h = NULL;
   2160  1.1.1.3  christos       asection *def_sec = NULL;
   2161  1.1.1.3  christos 
   2162  1.1.1.3  christos       if ((r_type != R_LARCH_64 && r_type != R_LARCH_32)
   2163  1.1.1.3  christos 	  || rel->r_offset % 2 != 0)
   2164  1.1.1.3  christos 	continue;
   2165  1.1.1.3  christos 
   2166  1.1.1.3  christos       /* The logical below must match loongarch_elf_relocate_section.  */
   2167  1.1.1.3  christos       if (r_symndx < symtab_hdr->sh_info)
   2168  1.1.1.3  christos 	{
   2169  1.1.1.3  christos 	  /* A local symbol.  */
   2170  1.1.1.3  christos 	  Elf_Internal_Sym *isym;
   2171  1.1.1.3  christos 	  isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, input_bfd,
   2172  1.1.1.3  christos 					r_symndx);
   2173  1.1.1.3  christos 	  BFD_ASSERT(isym != NULL);
   2174  1.1.1.3  christos 
   2175  1.1.1.3  christos 	  /* Local STT_GNU_IFUNC symbol uses R_LARCH_IRELATIVE for
   2176  1.1.1.3  christos 	     R_LARCH_NN, not R_LARCH_RELATIVE.  */
   2177  1.1.1.3  christos 	  if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
   2178  1.1.1.3  christos 	    continue;
   2179  1.1.1.3  christos 	  def_sec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
   2180  1.1.1.3  christos 	}
   2181  1.1.1.3  christos       else
   2182  1.1.1.3  christos 	{
   2183  1.1.1.3  christos 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
   2184  1.1.1.3  christos 	  while (h->root.type == bfd_link_hash_indirect
   2185  1.1.1.3  christos 		 || h->root.type == bfd_link_hash_warning)
   2186  1.1.1.3  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
   2187  1.1.1.3  christos 
   2188  1.1.1.3  christos 	  /* Filter out symbols that cannot have a relative reloc.  */
   2189  1.1.1.3  christos 	  if (h->dyn_relocs == NULL)
   2190  1.1.1.3  christos 	    continue;
   2191  1.1.1.3  christos 	  if (bfd_is_abs_symbol (&h->root))
   2192  1.1.1.3  christos 	    continue;
   2193  1.1.1.3  christos 	  if (h->type == STT_GNU_IFUNC)
   2194  1.1.1.3  christos 	    continue;
   2195  1.1.1.3  christos 
   2196  1.1.1.3  christos 	  if (h->root.type == bfd_link_hash_defined
   2197  1.1.1.3  christos 	      || h->root.type == bfd_link_hash_defweak)
   2198  1.1.1.3  christos 	    def_sec = h->root.u.def.section;
   2199  1.1.1.3  christos 
   2200  1.1.1.3  christos 	  /* On LoongArch an R_LARCH_NN against undefined weak symbol
   2201  1.1.1.3  christos 	     is never converted to R_LARCH_RELATIVE: we don't have
   2202  1.1.1.3  christos 	     -z dynamic-undefined-weak, thus the reloc is either removed
   2203  1.1.1.3  christos 	     (if the symbol is LARCH_REF_LOCAL) or kept (otherwise).  */
   2204  1.1.1.3  christos 	  if (h->root.type == bfd_link_hash_undefweak)
   2205  1.1.1.3  christos 	    continue;
   2206  1.1.1.3  christos 
   2207  1.1.1.3  christos 	  if (!LARCH_REF_LOCAL (info, h))
   2208  1.1.1.3  christos 	    continue;
   2209  1.1.1.3  christos 	}
   2210  1.1.1.3  christos 
   2211  1.1.1.3  christos       if (!def_sec || discarded_section (def_sec))
   2212  1.1.1.3  christos 	continue;
   2213  1.1.1.3  christos 
   2214  1.1.1.3  christos       if (!record_relr (htab, sec, rel->r_offset, sreloc))
   2215  1.1.1.3  christos 	return false;
   2216  1.1.1.3  christos     }
   2217  1.1.1.3  christos 
   2218  1.1.1.3  christos   return true;
   2219  1.1.1.3  christos }
   2220  1.1.1.3  christos 
   2221  1.1.1.3  christos static int
   2222  1.1.1.3  christos cmp_relr_addr (const void *p, const void *q)
   2223  1.1.1.3  christos {
   2224  1.1.1.3  christos   const bfd_vma *a = p, *b = q;
   2225  1.1.1.3  christos   return (*a > *b) - (*a < *b);
   2226  1.1.1.3  christos }
   2227  1.1.1.3  christos 
   2228  1.1.1.3  christos static bool
   2229  1.1.1.3  christos sort_relr (struct bfd_link_info *info,
   2230  1.1.1.3  christos 	   struct loongarch_elf_link_hash_table *htab)
   2231  1.1.1.3  christos {
   2232  1.1.1.3  christos   if (htab->relr_count == 0)
   2233  1.1.1.3  christos     return true;
   2234  1.1.1.3  christos 
   2235  1.1.1.3  christos   bfd_vma *addr = htab->relr_sorted;
   2236  1.1.1.3  christos   if (!addr)
   2237  1.1.1.3  christos     {
   2238  1.1.1.3  christos       addr = bfd_malloc (htab->relr_count * sizeof (*addr));
   2239  1.1.1.3  christos       if (!addr)
   2240  1.1.1.3  christos 	return false;
   2241  1.1.1.3  christos       htab->relr_sorted = addr;
   2242  1.1.1.3  christos     }
   2243  1.1.1.3  christos 
   2244  1.1.1.3  christos   for (bfd_size_type i = 0; i < htab->relr_count; i++)
   2245  1.1.1.3  christos     {
   2246  1.1.1.3  christos       bfd_vma off = _bfd_elf_section_offset (info->output_bfd, info,
   2247  1.1.1.3  christos 					     htab->relr[i].sec,
   2248  1.1.1.3  christos 					     htab->relr[i].off);
   2249  1.1.1.3  christos       addr[i] = htab->relr[i].sec->output_section->vma
   2250  1.1.1.3  christos 		+ htab->relr[i].sec->output_offset + off;
   2251  1.1.1.3  christos     }
   2252  1.1.1.3  christos   qsort(addr, htab->relr_count, sizeof (*addr), cmp_relr_addr);
   2253  1.1.1.3  christos   return true;
   2254  1.1.1.3  christos }
   2255  1.1.1.3  christos 
   2256  1.1.1.3  christos static bool
   2257  1.1.1.3  christos loongarch_elf_size_relative_relocs (struct bfd_link_info *info,
   2258  1.1.1.3  christos 				    bool *need_layout)
   2259  1.1.1.3  christos {
   2260  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab =
   2261  1.1.1.3  christos     loongarch_elf_hash_table (info);
   2262  1.1.1.3  christos   asection *srelrdyn = htab->elf.srelrdyn;
   2263  1.1.1.3  christos 
   2264  1.1.1.3  christos   *need_layout = false;
   2265  1.1.1.3  christos 
   2266  1.1.1.3  christos   if (!sort_relr (info, htab))
   2267  1.1.1.3  christos     return false;
   2268  1.1.1.3  christos   bfd_vma *addr = htab->relr_sorted;
   2269  1.1.1.3  christos 
   2270  1.1.1.3  christos   BFD_ASSERT (srelrdyn != NULL);
   2271  1.1.1.3  christos   bfd_size_type oldsize = srelrdyn->size;
   2272  1.1.1.3  christos   srelrdyn->size = 0;
   2273  1.1.1.3  christos   for (bfd_size_type i = 0; i < htab->relr_count; )
   2274  1.1.1.3  christos     {
   2275  1.1.1.3  christos       bfd_vma base = addr[i];
   2276  1.1.1.3  christos       i++;
   2277  1.1.1.3  christos       srelrdyn->size += NN / 8;
   2278  1.1.1.3  christos       base += NN / 8;
   2279  1.1.1.3  christos       while (1)
   2280  1.1.1.3  christos 	{
   2281  1.1.1.3  christos 	  bfd_size_type start_i = i;
   2282  1.1.1.3  christos 	  while (i < htab->relr_count
   2283  1.1.1.3  christos 		 && addr[i] - base < (NN - 1) * (NN / 8)
   2284  1.1.1.3  christos 		 && (addr[i] - base) % (NN / 8) == 0)
   2285  1.1.1.3  christos 	    i++;
   2286  1.1.1.3  christos 	  if (i == start_i)
   2287  1.1.1.3  christos 	    break;
   2288  1.1.1.3  christos 	  srelrdyn->size += NN / 8;
   2289  1.1.1.3  christos 	  base += (NN - 1) * (NN / 8);
   2290  1.1.1.3  christos 	}
   2291  1.1.1.3  christos     }
   2292  1.1.1.3  christos   if (srelrdyn->size != oldsize)
   2293  1.1.1.3  christos     {
   2294  1.1.1.3  christos       *need_layout = true;
   2295  1.1.1.3  christos       /* Stop after a few iterations in case the layout does not converge,
   2296  1.1.1.3  christos 	 but we can only stop when the size would shrink (and pad the
   2297  1.1.1.3  christos 	 spare space with 1.  */
   2298  1.1.1.3  christos       if (htab->relr_layout_iter++ > 5 && srelrdyn->size < oldsize)
   2299  1.1.1.3  christos 	{
   2300  1.1.1.3  christos 	  srelrdyn->size = oldsize;
   2301  1.1.1.3  christos 	  *need_layout = false;
   2302  1.1.1.3  christos 	}
   2303  1.1.1.3  christos     }
   2304  1.1.1.3  christos 
   2305  1.1.1.3  christos   htab->layout_mutating_for_relr = *need_layout;
   2306  1.1.1.3  christos   return true;
   2307  1.1.1.3  christos }
   2308  1.1.1.3  christos 
   2309  1.1.1.3  christos static bool
   2310  1.1.1.3  christos loongarch_elf_finish_relative_relocs (struct bfd_link_info *info)
   2311  1.1.1.3  christos {
   2312  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab =
   2313  1.1.1.3  christos     loongarch_elf_hash_table (info);
   2314  1.1.1.3  christos   asection *srelrdyn = htab->elf.srelrdyn;
   2315  1.1.1.3  christos   bfd *dynobj = htab->elf.dynobj;
   2316  1.1.1.3  christos 
   2317  1.1.1.3  christos   if (!srelrdyn || srelrdyn->size == 0)
   2318  1.1.1.3  christos     return true;
   2319  1.1.1.3  christos 
   2320  1.1.1.3  christos   srelrdyn->contents = bfd_alloc (dynobj, srelrdyn->size);
   2321  1.1.1.3  christos   if (!srelrdyn->contents)
   2322  1.1.1.3  christos     return false;
   2323  1.1.1.3  christos   srelrdyn->alloced = 1;
   2324  1.1.1.3  christos 
   2325  1.1.1.3  christos   bfd_vma *addr = htab->relr_sorted;
   2326  1.1.1.3  christos   bfd_byte *loc = srelrdyn->contents;
   2327  1.1.1.3  christos   for (bfd_size_type i = 0; i < htab->relr_count; )
   2328  1.1.1.3  christos     {
   2329  1.1.1.3  christos       bfd_vma base = addr[i];
   2330  1.1.1.3  christos       i++;
   2331  1.1.1.3  christos       bfd_put_NN (dynobj, base, loc);
   2332  1.1.1.3  christos       loc += NN / 8;
   2333  1.1.1.3  christos       base += NN / 8;
   2334  1.1.1.3  christos       while (1)
   2335  1.1.1.3  christos 	{
   2336  1.1.1.3  christos 	  uintNN_t bits = 0;
   2337  1.1.1.3  christos 	  while (i < htab->relr_count)
   2338  1.1.1.3  christos 	    {
   2339  1.1.1.3  christos 	      bfd_vma delta = addr[i] - base;
   2340  1.1.1.3  christos 	      if (delta >= (NN - 1) * (NN / 8) || delta % (NN / 8) != 0)
   2341  1.1.1.3  christos 		break;
   2342  1.1.1.3  christos 	      bits |= (uintNN_t) 1 << (delta / (NN / 8));
   2343  1.1.1.3  christos 	      i++;
   2344  1.1.1.3  christos 	    }
   2345  1.1.1.3  christos 	  if (bits == 0)
   2346  1.1.1.3  christos 	    break;
   2347  1.1.1.3  christos 	  bfd_put_NN (dynobj, (bits << 1) | 1, loc);
   2348  1.1.1.3  christos 	  loc += NN / 8;
   2349  1.1.1.3  christos 	  base += (NN - 1) * (NN / 8);
   2350  1.1.1.3  christos 	}
   2351  1.1.1.3  christos     }
   2352  1.1.1.3  christos 
   2353  1.1.1.3  christos   free (addr);
   2354  1.1.1.3  christos   htab->relr_sorted = NULL;
   2355  1.1.1.3  christos 
   2356  1.1.1.3  christos   /* Pad any excess with 1's, a do-nothing encoding.  */
   2357  1.1.1.3  christos   while (loc < srelrdyn->contents + srelrdyn->size)
   2358  1.1.1.3  christos     {
   2359  1.1.1.3  christos       bfd_put_NN (dynobj, 1, loc);
   2360  1.1.1.3  christos       loc += NN / 8;
   2361  1.1.1.3  christos     }
   2362  1.1.1.3  christos 
   2363  1.1.1.3  christos   return true;
   2364  1.1.1.3  christos }
   2365  1.1.1.3  christos 
   2366  1.1.1.3  christos static bool
   2367  1.1.1.3  christos loongarch_elf_late_size_sections (bfd *output_bfd,
   2368  1.1.1.3  christos 				  struct bfd_link_info *info)
   2369      1.1  christos {
   2370      1.1  christos   struct loongarch_elf_link_hash_table *htab;
   2371      1.1  christos   bfd *dynobj;
   2372      1.1  christos   asection *s;
   2373      1.1  christos   bfd *ibfd;
   2374      1.1  christos 
   2375      1.1  christos   htab = loongarch_elf_hash_table (info);
   2376      1.1  christos   BFD_ASSERT (htab != NULL);
   2377      1.1  christos   dynobj = htab->elf.dynobj;
   2378  1.1.1.3  christos   if (dynobj == NULL)
   2379  1.1.1.3  christos     return true;
   2380      1.1  christos 
   2381      1.1  christos   if (htab->elf.dynamic_sections_created)
   2382      1.1  christos     {
   2383      1.1  christos       /* Set the contents of the .interp section to the interpreter.  */
   2384      1.1  christos       if (bfd_link_executable (info) && !info->nointerp)
   2385      1.1  christos 	{
   2386      1.1  christos 	  const char *interpreter;
   2387      1.1  christos 	  s = bfd_get_linker_section (dynobj, ".interp");
   2388      1.1  christos 	  BFD_ASSERT (s != NULL);
   2389  1.1.1.2  christos 
   2390  1.1.1.2  christos 	  if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS32)
   2391      1.1  christos 	    interpreter = "/lib32/ld.so.1";
   2392  1.1.1.2  christos 	  else if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS64)
   2393      1.1  christos 	    interpreter = "/lib64/ld.so.1";
   2394      1.1  christos 	  else
   2395      1.1  christos 	    interpreter = "/lib/ld.so.1";
   2396  1.1.1.2  christos 
   2397      1.1  christos 	  s->contents = (unsigned char *) interpreter;
   2398  1.1.1.3  christos 	  s->alloced = 1;
   2399      1.1  christos 	  s->size = strlen (interpreter) + 1;
   2400      1.1  christos 	}
   2401      1.1  christos     }
   2402      1.1  christos 
   2403      1.1  christos   /* Set up .got offsets for local syms, and space for local dynamic
   2404      1.1  christos      relocs.  */
   2405      1.1  christos   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
   2406      1.1  christos     {
   2407      1.1  christos       bfd_signed_vma *local_got;
   2408      1.1  christos       bfd_signed_vma *end_local_got;
   2409      1.1  christos       char *local_tls_type;
   2410      1.1  christos       bfd_size_type locsymcount;
   2411      1.1  christos       Elf_Internal_Shdr *symtab_hdr;
   2412      1.1  christos       asection *srel;
   2413      1.1  christos 
   2414      1.1  christos       if (!is_loongarch_elf (ibfd))
   2415      1.1  christos 	continue;
   2416      1.1  christos 
   2417      1.1  christos       for (s = ibfd->sections; s != NULL; s = s->next)
   2418      1.1  christos 	{
   2419      1.1  christos 	  struct elf_dyn_relocs *p;
   2420      1.1  christos 
   2421      1.1  christos 	  for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
   2422      1.1  christos 	    {
   2423      1.1  christos 	      p->count -= p->pc_count;
   2424      1.1  christos 	      if (!bfd_is_abs_section (p->sec)
   2425      1.1  christos 		  && bfd_is_abs_section (p->sec->output_section))
   2426      1.1  christos 		{
   2427      1.1  christos 		  /* Input section has been discarded, either because
   2428      1.1  christos 		     it is a copy of a linkonce section or due to
   2429      1.1  christos 		     linker script /DISCARD/, so we'll be discarding
   2430      1.1  christos 		     the relocs too.  */
   2431      1.1  christos 		}
   2432      1.1  christos 	      else if (0 < p->count)
   2433      1.1  christos 		{
   2434      1.1  christos 		  srel = elf_section_data (p->sec)->sreloc;
   2435      1.1  christos 		  srel->size += p->count * sizeof (ElfNN_External_Rela);
   2436      1.1  christos 		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
   2437      1.1  christos 		    info->flags |= DF_TEXTREL;
   2438      1.1  christos 		}
   2439      1.1  christos 	    }
   2440      1.1  christos 	}
   2441      1.1  christos 
   2442      1.1  christos       local_got = elf_local_got_refcounts (ibfd);
   2443      1.1  christos       if (!local_got)
   2444      1.1  christos 	continue;
   2445      1.1  christos 
   2446      1.1  christos       symtab_hdr = &elf_symtab_hdr (ibfd);
   2447      1.1  christos       locsymcount = symtab_hdr->sh_info;
   2448      1.1  christos       end_local_got = local_got + locsymcount;
   2449      1.1  christos       local_tls_type = _bfd_loongarch_elf_local_got_tls_type (ibfd);
   2450      1.1  christos       s = htab->elf.sgot;
   2451      1.1  christos       srel = htab->elf.srelgot;
   2452      1.1  christos       for (; local_got < end_local_got; ++local_got, ++local_tls_type)
   2453      1.1  christos 	{
   2454      1.1  christos 	  if (0 < *local_got)
   2455      1.1  christos 	    {
   2456      1.1  christos 	      *local_got = s->size;
   2457  1.1.1.2  christos 	      if (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
   2458  1.1.1.2  christos 		{
   2459  1.1.1.2  christos 		  /* TLS gd use two got.  */
   2460  1.1.1.2  christos 		  if (*local_tls_type & GOT_TLS_GD)
   2461  1.1.1.2  christos 		    {
   2462  1.1.1.2  christos 		      s->size += 2 * GOT_ENTRY_SIZE;
   2463  1.1.1.2  christos 		      if (!bfd_link_executable (info))
   2464  1.1.1.2  christos 			srel->size += sizeof (ElfNN_External_Rela);
   2465  1.1.1.2  christos 		    }
   2466      1.1  christos 
   2467  1.1.1.2  christos 		  /* TLS_DESC use two got.  */
   2468  1.1.1.2  christos 		  if (*local_tls_type & GOT_TLS_GDESC)
   2469  1.1.1.2  christos 		    {
   2470  1.1.1.2  christos 		      s->size += 2 * GOT_ENTRY_SIZE;
   2471  1.1.1.2  christos 		      srel->size += sizeof (ElfNN_External_Rela);
   2472  1.1.1.2  christos 		    }
   2473      1.1  christos 
   2474  1.1.1.2  christos 		  /* TLS ie and use one got.  */
   2475  1.1.1.2  christos 		  if (*local_tls_type & GOT_TLS_IE)
   2476  1.1.1.2  christos 		    {
   2477  1.1.1.2  christos 		      s->size += GOT_ENTRY_SIZE;
   2478  1.1.1.2  christos 		      if (!bfd_link_executable (info))
   2479  1.1.1.2  christos 			srel->size += sizeof (ElfNN_External_Rela);
   2480  1.1.1.2  christos 		    }
   2481  1.1.1.2  christos 		}
   2482  1.1.1.2  christos 	      else
   2483  1.1.1.2  christos 		{
   2484  1.1.1.2  christos 		  s->size += GOT_ENTRY_SIZE;
   2485  1.1.1.2  christos 		  srel->size += sizeof (ElfNN_External_Rela);
   2486  1.1.1.2  christos 		}
   2487      1.1  christos 	    }
   2488      1.1  christos 	  else
   2489      1.1  christos 	    *local_got = MINUS_ONE;
   2490      1.1  christos 	}
   2491      1.1  christos     }
   2492      1.1  christos 
   2493      1.1  christos   /* Allocate global sym .plt and .got entries, and space for global
   2494      1.1  christos      sym dynamic relocs.  */
   2495      1.1  christos   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
   2496      1.1  christos 
   2497  1.1.1.3  christos   /* Allocate global ifunc sym .plt and .got entries, and space for
   2498  1.1.1.3  christos      *preemptible* ifunc sym dynamic relocs.  Note that we must do it
   2499  1.1.1.3  christos      for *all* preemptible ifunc (including local ifuncs and STV_HIDDEN
   2500  1.1.1.3  christos      ifuncs) before doing it for any non-preemptible ifunc symbol:
   2501  1.1.1.3  christos      assuming we are not so careful, when we link a shared library the
   2502  1.1.1.3  christos      correlation of .plt and .rela.plt might look like:
   2503  1.1.1.3  christos 
   2504  1.1.1.3  christos 				idx in .plt	idx in .rela.plt
   2505  1.1.1.3  christos 	ext_func1@plt		0		0
   2506  1.1.1.3  christos 	ext_func2@plt		1		1
   2507  1.1.1.3  christos 	ext_func3@plt		2		2
   2508  1.1.1.3  christos 	hidden_ifunc1@plt	3		None: it's in .rela.got
   2509  1.1.1.3  christos 	hidden_ifunc2@plt	4		None: it's in .rela.got
   2510  1.1.1.3  christos 	normal_ifunc1@plt	5	!=	3
   2511  1.1.1.3  christos 	normal_ifunc2@plt	6	!=	4
   2512  1.1.1.3  christos 	local_ifunc@plt		7		None: it's in .rela.got
   2513  1.1.1.3  christos 
   2514  1.1.1.3  christos      Now oops the indices for normal_ifunc{1,2} in .rela.plt were different
   2515  1.1.1.3  christos      from the indices in .plt :(.  This would break finish_dynamic_symbol
   2516  1.1.1.3  christos      which assumes the index in .rela.plt matches the index in .plt.
   2517  1.1.1.3  christos 
   2518  1.1.1.3  christos      So let's be careful and make it correct:
   2519  1.1.1.3  christos 
   2520  1.1.1.3  christos 				idx in .plt	idx in .rela.plt
   2521  1.1.1.3  christos 	ext_func1@plt		0		0
   2522  1.1.1.3  christos 	ext_func2@plt		1		1
   2523  1.1.1.3  christos 	ext_func3@plt		2		2
   2524  1.1.1.3  christos 	normal_ifunc1@plt	3		3
   2525  1.1.1.3  christos 	normal_ifunc2@plt	4		4
   2526  1.1.1.3  christos 	hidden_ifunc1@plt	5		None: it's in .rela.got
   2527  1.1.1.3  christos 	hidden_ifunc2@plt	6		None: it's in .rela.got
   2528  1.1.1.3  christos 	local_ifunc@plt		7		None: it's in .rela.got
   2529  1.1.1.3  christos 
   2530  1.1.1.3  christos      Now normal_ifuncs first.  */
   2531  1.1.1.3  christos   elf_link_hash_traverse (&htab->elf,
   2532  1.1.1.3  christos 			  elfNN_allocate_ifunc_dynrelocs_ref_global, info);
   2533  1.1.1.3  christos 
   2534  1.1.1.3  christos   /* Next hidden_ifuncs follows.  */
   2535  1.1.1.3  christos   elf_link_hash_traverse (&htab->elf,
   2536  1.1.1.3  christos 			  elfNN_allocate_ifunc_dynrelocs_ref_local, info);
   2537      1.1  christos 
   2538  1.1.1.3  christos   /* Finally local_ifuncs.  */
   2539      1.1  christos   htab_traverse (htab->loc_hash_table,
   2540  1.1.1.2  christos 		 elfNN_allocate_local_ifunc_dynrelocs, info);
   2541      1.1  christos 
   2542      1.1  christos   /* Don't allocate .got.plt section if there are no PLT.  */
   2543      1.1  christos   if (htab->elf.sgotplt && htab->elf.sgotplt->size == GOTPLT_HEADER_SIZE
   2544      1.1  christos       && (htab->elf.splt == NULL || htab->elf.splt->size == 0))
   2545      1.1  christos     htab->elf.sgotplt->size = 0;
   2546      1.1  christos 
   2547  1.1.1.3  christos   if (info->enable_dt_relr && !bfd_link_relocatable (info))
   2548  1.1.1.3  christos     {
   2549  1.1.1.3  christos       elf_link_hash_traverse (&htab->elf, record_relr_dyn_got_relocs, info);
   2550  1.1.1.3  christos 
   2551  1.1.1.3  christos       for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
   2552  1.1.1.3  christos 	{
   2553  1.1.1.3  christos 	  if (!is_loongarch_elf (ibfd))
   2554  1.1.1.3  christos 	    continue;
   2555  1.1.1.3  christos 
   2556  1.1.1.3  christos 	  for (s = ibfd->sections; s != NULL; s = s->next)
   2557  1.1.1.3  christos 	    if (!record_relr_non_got_relocs (ibfd, info, s))
   2558  1.1.1.3  christos 	      return false;
   2559  1.1.1.3  christos 
   2560  1.1.1.3  christos 	  if (!record_relr_local_got_relocs (ibfd, info))
   2561  1.1.1.3  christos 	    return false;
   2562  1.1.1.3  christos 	}
   2563  1.1.1.3  christos     }
   2564  1.1.1.3  christos 
   2565      1.1  christos   /* The check_relocs and adjust_dynamic_symbol entry points have
   2566      1.1  christos      determined the sizes of the various dynamic sections.  Allocate
   2567      1.1  christos      memory for them.  */
   2568      1.1  christos   for (s = dynobj->sections; s != NULL; s = s->next)
   2569      1.1  christos     {
   2570      1.1  christos       if ((s->flags & SEC_LINKER_CREATED) == 0)
   2571      1.1  christos 	continue;
   2572      1.1  christos 
   2573      1.1  christos       if (s == htab->elf.splt || s == htab->elf.iplt || s == htab->elf.sgot
   2574      1.1  christos 	  || s == htab->elf.sgotplt || s == htab->elf.igotplt
   2575      1.1  christos 	  || s == htab->elf.sdynbss || s == htab->elf.sdynrelro)
   2576      1.1  christos 	{
   2577      1.1  christos 	  /* Strip this section if we don't need it; see the
   2578      1.1  christos 	     comment below.  */
   2579      1.1  christos 	}
   2580      1.1  christos       else if (strncmp (s->name, ".rela", 5) == 0)
   2581      1.1  christos 	{
   2582      1.1  christos 	  if (s->size != 0)
   2583      1.1  christos 	    {
   2584      1.1  christos 	      /* We use the reloc_count field as a counter if we need
   2585      1.1  christos 		 to copy relocs into the output file.  */
   2586      1.1  christos 	      s->reloc_count = 0;
   2587      1.1  christos 	    }
   2588      1.1  christos 	}
   2589  1.1.1.3  christos       else if (s == htab->elf.srelrdyn && htab->relr_count == 0)
   2590  1.1.1.3  christos 	{
   2591  1.1.1.3  christos 	  /* Remove .relr.dyn based on relr_count, not size, since
   2592  1.1.1.3  christos 	     it is not sized yet.  */
   2593  1.1.1.3  christos 	  s->flags |= SEC_EXCLUDE;
   2594  1.1.1.3  christos 	  /* Allocate contents later.  */
   2595  1.1.1.3  christos 	  continue;
   2596  1.1.1.3  christos 	}
   2597      1.1  christos       else
   2598      1.1  christos 	{
   2599      1.1  christos 	  /* It's not one of our sections.  */
   2600      1.1  christos 	  continue;
   2601      1.1  christos 	}
   2602      1.1  christos 
   2603      1.1  christos       if (s->size == 0)
   2604      1.1  christos 	{
   2605      1.1  christos 	  /* If we don't need this section, strip it from the
   2606      1.1  christos 	     output file.  This is mostly to handle .rela.bss and
   2607      1.1  christos 	     .rela.plt.  We must create both sections in
   2608      1.1  christos 	     create_dynamic_sections, because they must be created
   2609      1.1  christos 	     before the linker maps input sections to output
   2610      1.1  christos 	     sections.  The linker does that before
   2611      1.1  christos 	     adjust_dynamic_symbol is called, and it is that
   2612      1.1  christos 	     function which decides whether anything needs to go
   2613      1.1  christos 	     into these sections.  */
   2614      1.1  christos 	  s->flags |= SEC_EXCLUDE;
   2615      1.1  christos 	  continue;
   2616      1.1  christos 	}
   2617      1.1  christos 
   2618      1.1  christos       if ((s->flags & SEC_HAS_CONTENTS) == 0)
   2619      1.1  christos 	continue;
   2620      1.1  christos 
   2621      1.1  christos       /* Allocate memory for the section contents.  Zero the memory
   2622      1.1  christos 	 for the benefit of .rela.plt, which has 4 unused entries
   2623      1.1  christos 	 at the beginning, and we don't want garbage.  */
   2624      1.1  christos       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
   2625      1.1  christos       if (s->contents == NULL)
   2626      1.1  christos 	return false;
   2627  1.1.1.3  christos       s->alloced = 1;
   2628      1.1  christos     }
   2629      1.1  christos 
   2630      1.1  christos   if (elf_hash_table (info)->dynamic_sections_created)
   2631      1.1  christos     {
   2632      1.1  christos       /* Add some entries to the .dynamic section.  We fill in the
   2633      1.1  christos 	 values later, in loongarch_elf_finish_dynamic_sections, but we
   2634      1.1  christos 	 must add the entries now so that we get the correct size for
   2635      1.1  christos 	 the .dynamic section.  The DT_DEBUG entry is filled in by the
   2636      1.1  christos 	 dynamic linker and used by the debugger.  */
   2637      1.1  christos #define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
   2638      1.1  christos 
   2639      1.1  christos       if (bfd_link_executable (info))
   2640      1.1  christos 	{
   2641      1.1  christos 	  if (!add_dynamic_entry (DT_DEBUG, 0))
   2642      1.1  christos 	    return false;
   2643      1.1  christos 	}
   2644      1.1  christos 
   2645      1.1  christos       if (htab->elf.srelplt->size != 0)
   2646      1.1  christos 	{
   2647      1.1  christos 	  if (!add_dynamic_entry (DT_PLTGOT, 0)
   2648      1.1  christos 	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
   2649      1.1  christos 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
   2650      1.1  christos 	      || !add_dynamic_entry (DT_JMPREL, 0))
   2651      1.1  christos 	    return false;
   2652      1.1  christos 	}
   2653      1.1  christos 
   2654      1.1  christos       if (!add_dynamic_entry (DT_RELA, 0)
   2655      1.1  christos 	  || !add_dynamic_entry (DT_RELASZ, 0)
   2656      1.1  christos 	  || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
   2657      1.1  christos 	return false;
   2658      1.1  christos 
   2659      1.1  christos       /* If any dynamic relocs apply to a read-only section,
   2660      1.1  christos 	 then we need a DT_TEXTREL entry.  */
   2661      1.1  christos       if ((info->flags & DF_TEXTREL) == 0)
   2662      1.1  christos 	elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
   2663      1.1  christos 
   2664      1.1  christos       if (info->flags & DF_TEXTREL)
   2665      1.1  christos 	{
   2666      1.1  christos 	  if (!add_dynamic_entry (DT_TEXTREL, 0))
   2667      1.1  christos 	    return false;
   2668      1.1  christos 	  /* Clear the DF_TEXTREL flag.  It will be set again if we
   2669      1.1  christos 	     write out an actual text relocation; we may not, because
   2670      1.1  christos 	     at this point we do not know whether e.g.  any .eh_frame
   2671      1.1  christos 	     absolute relocations have been converted to PC-relative.  */
   2672      1.1  christos 	  info->flags &= ~DF_TEXTREL;
   2673      1.1  christos 	}
   2674      1.1  christos     }
   2675      1.1  christos #undef add_dynamic_entry
   2676      1.1  christos 
   2677      1.1  christos   return true;
   2678      1.1  christos }
   2679      1.1  christos 
   2680      1.1  christos #define LARCH_LD_STACK_DEPTH 16
   2681      1.1  christos static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
   2682      1.1  christos static size_t larch_stack_top = 0;
   2683      1.1  christos 
   2684      1.1  christos static bfd_reloc_status_type
   2685      1.1  christos loongarch_push (int64_t val)
   2686      1.1  christos {
   2687      1.1  christos   if (LARCH_LD_STACK_DEPTH <= larch_stack_top)
   2688      1.1  christos     return bfd_reloc_outofrange;
   2689      1.1  christos   larch_opc_stack[larch_stack_top++] = val;
   2690      1.1  christos   return bfd_reloc_ok;
   2691      1.1  christos }
   2692      1.1  christos 
   2693      1.1  christos static bfd_reloc_status_type
   2694      1.1  christos loongarch_pop (int64_t *val)
   2695      1.1  christos {
   2696      1.1  christos   if (larch_stack_top == 0)
   2697      1.1  christos     return bfd_reloc_outofrange;
   2698      1.1  christos   BFD_ASSERT (val);
   2699      1.1  christos   *val = larch_opc_stack[--larch_stack_top];
   2700      1.1  christos   return bfd_reloc_ok;
   2701      1.1  christos }
   2702      1.1  christos 
   2703      1.1  christos static bfd_reloc_status_type
   2704      1.1  christos loongarch_top (int64_t *val)
   2705      1.1  christos {
   2706      1.1  christos   if (larch_stack_top == 0)
   2707      1.1  christos     return bfd_reloc_outofrange;
   2708      1.1  christos   BFD_ASSERT (val);
   2709      1.1  christos   *val = larch_opc_stack[larch_stack_top - 1];
   2710      1.1  christos   return bfd_reloc_ok;
   2711      1.1  christos }
   2712      1.1  christos 
   2713      1.1  christos static void
   2714      1.1  christos loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   2715      1.1  christos {
   2716  1.1.1.2  christos   BFD_ASSERT (s && s->contents);
   2717      1.1  christos   const struct elf_backend_data *bed;
   2718      1.1  christos   bfd_byte *loc;
   2719      1.1  christos 
   2720      1.1  christos   bed = get_elf_backend_data (abfd);
   2721  1.1.1.2  christos   if (!(s->size > s->reloc_count * bed->s->sizeof_rela))
   2722  1.1.1.2  christos     BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela);
   2723      1.1  christos   loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
   2724      1.1  christos   bed->s->swap_reloca_out (abfd, rel, loc);
   2725      1.1  christos }
   2726      1.1  christos 
   2727      1.1  christos /* Check rel->r_offset in range of contents.  */
   2728      1.1  christos static bfd_reloc_status_type
   2729      1.1  christos loongarch_check_offset (const Elf_Internal_Rela *rel,
   2730      1.1  christos 			const asection *input_section)
   2731      1.1  christos {
   2732      1.1  christos   if (0 == strcmp(input_section->name, ".text")
   2733      1.1  christos       && rel->r_offset > input_section->size)
   2734      1.1  christos     return bfd_reloc_overflow;
   2735      1.1  christos 
   2736      1.1  christos   return bfd_reloc_ok;
   2737      1.1  christos }
   2738      1.1  christos 
   2739      1.1  christos #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3)	      \
   2740      1.1  christos   ({						      \
   2741      1.1  christos     bfd_reloc_status_type ret = loongarch_pop (&op2); \
   2742      1.1  christos     if (ret == bfd_reloc_ok)			      \
   2743      1.1  christos       {						      \
   2744      1.1  christos 	ret = loongarch_pop (&op1);		      \
   2745      1.1  christos 	if (ret == bfd_reloc_ok)		      \
   2746      1.1  christos 	  ret = loongarch_push (op3);		      \
   2747      1.1  christos       }						      \
   2748      1.1  christos     ret;					      \
   2749      1.1  christos    })
   2750      1.1  christos 
   2751  1.1.1.2  christos /* Write immediate to instructions.  */
   2752  1.1.1.2  christos 
   2753      1.1  christos static bfd_reloc_status_type
   2754      1.1  christos loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
   2755      1.1  christos 				  const asection *input_section ATTRIBUTE_UNUSED,
   2756      1.1  christos 				  reloc_howto_type *howto, bfd *input_bfd,
   2757      1.1  christos 				  bfd_byte *contents, bfd_vma reloc_val)
   2758      1.1  christos {
   2759  1.1.1.2  christos   /* Adjust the immediate based on alignment and
   2760  1.1.1.2  christos      its position in the instruction.  */
   2761  1.1.1.2  christos   if (!loongarch_adjust_reloc_bitsfield (input_bfd, howto, &reloc_val))
   2762      1.1  christos     return bfd_reloc_overflow;
   2763      1.1  christos 
   2764  1.1.1.2  christos   int bits = bfd_get_reloc_size (howto) * 8;
   2765  1.1.1.2  christos   uint64_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
   2766  1.1.1.2  christos 
   2767  1.1.1.2  christos   /* Write immediate to instruction.  */
   2768  1.1.1.2  christos   insn = (insn & ~howto->dst_mask) | (reloc_val & howto->dst_mask);
   2769      1.1  christos 
   2770      1.1  christos   bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
   2771      1.1  christos 
   2772      1.1  christos   return bfd_reloc_ok;
   2773      1.1  christos }
   2774      1.1  christos 
   2775      1.1  christos static bfd_reloc_status_type
   2776      1.1  christos perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
   2777      1.1  christos 		    reloc_howto_type *howto, bfd_vma value,
   2778      1.1  christos 		    bfd *input_bfd, bfd_byte *contents)
   2779      1.1  christos {
   2780      1.1  christos   int64_t opr1, opr2, opr3;
   2781      1.1  christos   bfd_reloc_status_type r = bfd_reloc_ok;
   2782      1.1  christos   int bits = bfd_get_reloc_size (howto) * 8;
   2783      1.1  christos 
   2784      1.1  christos   switch (ELFNN_R_TYPE (rel->r_info))
   2785      1.1  christos     {
   2786      1.1  christos     case R_LARCH_SOP_PUSH_PCREL:
   2787      1.1  christos     case R_LARCH_SOP_PUSH_ABSOLUTE:
   2788      1.1  christos     case R_LARCH_SOP_PUSH_GPREL:
   2789      1.1  christos     case R_LARCH_SOP_PUSH_TLS_TPREL:
   2790      1.1  christos     case R_LARCH_SOP_PUSH_TLS_GOT:
   2791      1.1  christos     case R_LARCH_SOP_PUSH_TLS_GD:
   2792      1.1  christos     case R_LARCH_SOP_PUSH_PLT_PCREL:
   2793      1.1  christos       r = loongarch_push (value);
   2794      1.1  christos       break;
   2795      1.1  christos 
   2796      1.1  christos     case R_LARCH_SOP_PUSH_DUP:
   2797      1.1  christos       r = loongarch_pop (&opr1);
   2798      1.1  christos       if (r == bfd_reloc_ok)
   2799      1.1  christos 	{
   2800      1.1  christos 	  r = loongarch_push (opr1);
   2801      1.1  christos 	  if (r == bfd_reloc_ok)
   2802      1.1  christos 	    r = loongarch_push (opr1);
   2803      1.1  christos 	}
   2804      1.1  christos       break;
   2805      1.1  christos 
   2806      1.1  christos     case R_LARCH_SOP_ASSERT:
   2807      1.1  christos       r = loongarch_pop (&opr1);
   2808      1.1  christos       if (r != bfd_reloc_ok || !opr1)
   2809      1.1  christos 	r = bfd_reloc_notsupported;
   2810      1.1  christos       break;
   2811      1.1  christos 
   2812      1.1  christos     case R_LARCH_SOP_NOT:
   2813      1.1  christos       r = loongarch_pop (&opr1);
   2814      1.1  christos       if (r == bfd_reloc_ok)
   2815      1.1  christos 	r = loongarch_push (!opr1);
   2816      1.1  christos       break;
   2817      1.1  christos 
   2818      1.1  christos     case R_LARCH_SOP_SUB:
   2819      1.1  christos       r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
   2820      1.1  christos       break;
   2821      1.1  christos 
   2822      1.1  christos     case R_LARCH_SOP_SL:
   2823      1.1  christos       r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
   2824      1.1  christos       break;
   2825      1.1  christos 
   2826      1.1  christos     case R_LARCH_SOP_SR:
   2827      1.1  christos       r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
   2828      1.1  christos       break;
   2829      1.1  christos 
   2830      1.1  christos     case R_LARCH_SOP_AND:
   2831      1.1  christos       r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
   2832      1.1  christos       break;
   2833      1.1  christos 
   2834      1.1  christos     case R_LARCH_SOP_ADD:
   2835      1.1  christos       r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
   2836      1.1  christos       break;
   2837      1.1  christos 
   2838      1.1  christos     case R_LARCH_SOP_IF_ELSE:
   2839      1.1  christos       r = loongarch_pop (&opr3);
   2840      1.1  christos       if (r == bfd_reloc_ok)
   2841      1.1  christos 	{
   2842      1.1  christos 	  r = loongarch_pop (&opr2);
   2843      1.1  christos 	  if (r == bfd_reloc_ok)
   2844      1.1  christos 	    {
   2845      1.1  christos 	      r = loongarch_pop (&opr1);
   2846      1.1  christos 	      if (r == bfd_reloc_ok)
   2847      1.1  christos 		r = loongarch_push (opr1 ? opr2 : opr3);
   2848      1.1  christos 	    }
   2849      1.1  christos 	}
   2850      1.1  christos       break;
   2851      1.1  christos 
   2852      1.1  christos     case R_LARCH_SOP_POP_32_S_10_5:
   2853      1.1  christos     case R_LARCH_SOP_POP_32_S_10_12:
   2854      1.1  christos     case R_LARCH_SOP_POP_32_S_10_16:
   2855      1.1  christos     case R_LARCH_SOP_POP_32_S_10_16_S2:
   2856  1.1.1.2  christos     case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
   2857  1.1.1.2  christos     case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
   2858      1.1  christos     case R_LARCH_SOP_POP_32_S_5_20:
   2859      1.1  christos     case R_LARCH_SOP_POP_32_U_10_12:
   2860      1.1  christos     case R_LARCH_SOP_POP_32_U:
   2861      1.1  christos       r = loongarch_pop (&opr1);
   2862      1.1  christos       if (r != bfd_reloc_ok)
   2863      1.1  christos 	break;
   2864      1.1  christos       r = loongarch_check_offset (rel, input_section);
   2865      1.1  christos       if (r != bfd_reloc_ok)
   2866      1.1  christos 	break;
   2867      1.1  christos 
   2868      1.1  christos       r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
   2869      1.1  christos 					    howto, input_bfd,
   2870      1.1  christos 					    contents, (bfd_vma)opr1);
   2871      1.1  christos       break;
   2872      1.1  christos 
   2873  1.1.1.2  christos     case R_LARCH_TLS_DTPREL32:
   2874  1.1.1.2  christos     case R_LARCH_32:
   2875  1.1.1.2  christos     case R_LARCH_TLS_DTPREL64:
   2876  1.1.1.2  christos     case R_LARCH_64:
   2877  1.1.1.2  christos       r = loongarch_check_offset (rel, input_section);
   2878  1.1.1.2  christos       if (r != bfd_reloc_ok)
   2879  1.1.1.2  christos 	break;
   2880      1.1  christos 
   2881  1.1.1.2  christos       bfd_put (bits, input_bfd, value, contents + rel->r_offset);
   2882  1.1.1.2  christos       break;
   2883      1.1  christos 
   2884  1.1.1.2  christos     /* LoongArch only has add/sub reloc pair, not has set/sub reloc pair.
   2885  1.1.1.2  christos        Because set/sub reloc pair not support multi-thread. While add/sub
   2886  1.1.1.2  christos        reloc pair process order not affect the final result.
   2887  1.1.1.2  christos 
   2888  1.1.1.2  christos        For add/sub reloc, the original value will be involved in the
   2889  1.1.1.2  christos        calculation. In order not to add/sub extra value, we write 0 to symbol
   2890  1.1.1.2  christos        address at assembly time.
   2891  1.1.1.2  christos 
   2892  1.1.1.2  christos        add/sub reloc bits determined by the value after symbol subtraction,
   2893  1.1.1.2  christos        not symbol value.
   2894  1.1.1.2  christos 
   2895  1.1.1.2  christos        add/sub reloc save part of the symbol value, so we only need to
   2896  1.1.1.2  christos        save howto->dst_mask bits.  */
   2897  1.1.1.2  christos     case R_LARCH_ADD6:
   2898  1.1.1.2  christos     case R_LARCH_SUB6:
   2899      1.1  christos       {
   2900  1.1.1.2  christos 	bfd_vma word = bfd_get (howto->bitsize, input_bfd,
   2901  1.1.1.2  christos 				contents + rel->r_offset);
   2902  1.1.1.2  christos 	word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
   2903  1.1.1.2  christos 	bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
   2904  1.1.1.2  christos 	r = bfd_reloc_ok;
   2905      1.1  christos 	break;
   2906      1.1  christos       }
   2907      1.1  christos 
   2908  1.1.1.2  christos     /* Not need to read the original value, just write the new value.  */
   2909      1.1  christos     case R_LARCH_ADD8:
   2910      1.1  christos     case R_LARCH_ADD16:
   2911      1.1  christos     case R_LARCH_ADD24:
   2912      1.1  christos     case R_LARCH_ADD32:
   2913      1.1  christos     case R_LARCH_ADD64:
   2914      1.1  christos     case R_LARCH_SUB8:
   2915      1.1  christos     case R_LARCH_SUB16:
   2916      1.1  christos     case R_LARCH_SUB24:
   2917      1.1  christos     case R_LARCH_SUB32:
   2918      1.1  christos     case R_LARCH_SUB64:
   2919  1.1.1.2  christos       {
   2920  1.1.1.2  christos 	/* Because add/sub reloc is processed separately,
   2921  1.1.1.2  christos 	   so the high bits is invalid.  */
   2922  1.1.1.2  christos 	bfd_vma word = value & howto->dst_mask;
   2923  1.1.1.2  christos 	bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
   2924  1.1.1.2  christos 	r = bfd_reloc_ok;
   2925  1.1.1.2  christos 	break;
   2926  1.1.1.2  christos       }
   2927  1.1.1.2  christos 
   2928  1.1.1.2  christos     case R_LARCH_ADD_ULEB128:
   2929  1.1.1.2  christos     case R_LARCH_SUB_ULEB128:
   2930  1.1.1.2  christos       {
   2931  1.1.1.2  christos 	unsigned int len = 0;
   2932  1.1.1.2  christos 	/* Before write uleb128, first read it to get it's length.  */
   2933  1.1.1.2  christos 	_bfd_read_unsigned_leb128 (input_bfd, contents + rel->r_offset, &len);
   2934  1.1.1.2  christos 	loongarch_write_unsigned_leb128 (contents + rel->r_offset, len, value);
   2935  1.1.1.2  christos 	r = bfd_reloc_ok;
   2936  1.1.1.2  christos 	break;
   2937  1.1.1.2  christos       }
   2938  1.1.1.2  christos 
   2939  1.1.1.2  christos     /* For eh_frame and debug info.  */
   2940  1.1.1.2  christos     case R_LARCH_32_PCREL:
   2941  1.1.1.2  christos     case R_LARCH_64_PCREL:
   2942  1.1.1.2  christos       {
   2943  1.1.1.2  christos 	value -= sec_addr (input_section) + rel->r_offset;
   2944  1.1.1.2  christos 	value += rel->r_addend;
   2945  1.1.1.3  christos 	/* Check overflow.  */
   2946  1.1.1.3  christos 	if (ELFNN_R_TYPE (rel->r_info) == R_LARCH_32_PCREL)
   2947  1.1.1.3  christos 	  {
   2948  1.1.1.3  christos 	    r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
   2949  1.1.1.3  christos 						  howto, input_bfd,
   2950  1.1.1.3  christos 						  contents, value);
   2951  1.1.1.3  christos 	  }
   2952  1.1.1.3  christos 	else
   2953  1.1.1.3  christos 	  {
   2954  1.1.1.3  christos 	    bfd_vma word = bfd_get (howto->bitsize, input_bfd,
   2955  1.1.1.3  christos 				    contents + rel->r_offset);
   2956  1.1.1.3  christos 	    word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
   2957  1.1.1.3  christos 	    bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
   2958  1.1.1.3  christos 	    r = bfd_reloc_ok;
   2959  1.1.1.3  christos 	  }
   2960  1.1.1.2  christos 	break;
   2961  1.1.1.2  christos       }
   2962  1.1.1.2  christos 
   2963  1.1.1.2  christos     /* New reloc type.
   2964  1.1.1.2  christos        R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20.  */
   2965  1.1.1.2  christos     case R_LARCH_B16:
   2966  1.1.1.2  christos     case R_LARCH_B21:
   2967  1.1.1.2  christos     case R_LARCH_B26:
   2968  1.1.1.2  christos     case R_LARCH_ABS_HI20:
   2969  1.1.1.2  christos     case R_LARCH_ABS_LO12:
   2970  1.1.1.2  christos     case R_LARCH_ABS64_LO20:
   2971  1.1.1.2  christos     case R_LARCH_ABS64_HI12:
   2972  1.1.1.2  christos     case R_LARCH_PCALA_HI20:
   2973  1.1.1.2  christos     case R_LARCH_PCALA_LO12:
   2974  1.1.1.2  christos     case R_LARCH_PCALA64_LO20:
   2975  1.1.1.2  christos     case R_LARCH_PCALA64_HI12:
   2976  1.1.1.2  christos     case R_LARCH_GOT_PC_HI20:
   2977  1.1.1.2  christos     case R_LARCH_GOT_PC_LO12:
   2978  1.1.1.2  christos     case R_LARCH_GOT64_PC_LO20:
   2979  1.1.1.2  christos     case R_LARCH_GOT64_PC_HI12:
   2980  1.1.1.2  christos     case R_LARCH_GOT_HI20:
   2981  1.1.1.2  christos     case R_LARCH_GOT_LO12:
   2982  1.1.1.2  christos     case R_LARCH_GOT64_LO20:
   2983  1.1.1.2  christos     case R_LARCH_GOT64_HI12:
   2984  1.1.1.2  christos     case R_LARCH_TLS_LE_HI20:
   2985  1.1.1.2  christos     case R_LARCH_TLS_LE_LO12:
   2986  1.1.1.2  christos     case R_LARCH_TLS_LE_HI20_R:
   2987  1.1.1.2  christos     case R_LARCH_TLS_LE_LO12_R:
   2988  1.1.1.2  christos     case R_LARCH_TLS_LE64_LO20:
   2989  1.1.1.2  christos     case R_LARCH_TLS_LE64_HI12:
   2990  1.1.1.2  christos     case R_LARCH_TLS_IE_PC_HI20:
   2991  1.1.1.2  christos     case R_LARCH_TLS_IE_PC_LO12:
   2992  1.1.1.2  christos     case R_LARCH_TLS_IE64_PC_LO20:
   2993  1.1.1.2  christos     case R_LARCH_TLS_IE64_PC_HI12:
   2994  1.1.1.2  christos     case R_LARCH_TLS_IE_HI20:
   2995  1.1.1.2  christos     case R_LARCH_TLS_IE_LO12:
   2996  1.1.1.2  christos     case R_LARCH_TLS_IE64_LO20:
   2997  1.1.1.2  christos     case R_LARCH_TLS_IE64_HI12:
   2998  1.1.1.2  christos     case R_LARCH_TLS_LD_PC_HI20:
   2999  1.1.1.2  christos     case R_LARCH_TLS_LD_HI20:
   3000  1.1.1.2  christos     case R_LARCH_TLS_GD_PC_HI20:
   3001  1.1.1.2  christos     case R_LARCH_TLS_GD_HI20:
   3002  1.1.1.2  christos     case R_LARCH_PCREL20_S2:
   3003  1.1.1.2  christos     case R_LARCH_CALL36:
   3004  1.1.1.2  christos     case R_LARCH_TLS_DESC_PC_HI20:
   3005  1.1.1.2  christos     case R_LARCH_TLS_DESC_PC_LO12:
   3006  1.1.1.2  christos     case R_LARCH_TLS_DESC64_PC_LO20:
   3007  1.1.1.2  christos     case R_LARCH_TLS_DESC64_PC_HI12:
   3008  1.1.1.2  christos     case R_LARCH_TLS_DESC_HI20:
   3009  1.1.1.2  christos     case R_LARCH_TLS_DESC_LO12:
   3010  1.1.1.2  christos     case R_LARCH_TLS_DESC64_LO20:
   3011  1.1.1.2  christos     case R_LARCH_TLS_DESC64_HI12:
   3012  1.1.1.2  christos     case R_LARCH_TLS_LD_PCREL20_S2:
   3013  1.1.1.2  christos     case R_LARCH_TLS_GD_PCREL20_S2:
   3014  1.1.1.2  christos     case R_LARCH_TLS_DESC_PCREL20_S2:
   3015      1.1  christos       r = loongarch_check_offset (rel, input_section);
   3016      1.1  christos       if (r != bfd_reloc_ok)
   3017      1.1  christos 	break;
   3018      1.1  christos 
   3019  1.1.1.2  christos       r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
   3020  1.1.1.2  christos 					    howto, input_bfd,
   3021  1.1.1.2  christos 					    contents, value);
   3022  1.1.1.2  christos       break;
   3023  1.1.1.2  christos 
   3024  1.1.1.2  christos     case R_LARCH_TLS_DESC_LD:
   3025  1.1.1.2  christos     case R_LARCH_TLS_DESC_CALL:
   3026  1.1.1.2  christos       r = bfd_reloc_ok;
   3027  1.1.1.2  christos       break;
   3028  1.1.1.2  christos 
   3029  1.1.1.2  christos     case R_LARCH_RELAX:
   3030  1.1.1.2  christos     case R_LARCH_TLS_LE_ADD_R:
   3031      1.1  christos       break;
   3032      1.1  christos 
   3033      1.1  christos     default:
   3034      1.1  christos       r = bfd_reloc_notsupported;
   3035      1.1  christos     }
   3036      1.1  christos   return r;
   3037      1.1  christos }
   3038      1.1  christos 
   3039      1.1  christos #define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
   3040      1.1  christos static struct
   3041      1.1  christos {
   3042      1.1  christos   bfd *bfd;
   3043      1.1  christos   asection *section;
   3044      1.1  christos   bfd_vma r_offset;
   3045      1.1  christos   int r_type;
   3046      1.1  christos   bfd_vma relocation;
   3047      1.1  christos   Elf_Internal_Sym *sym;
   3048      1.1  christos   struct elf_link_hash_entry *h;
   3049      1.1  christos   bfd_vma addend;
   3050      1.1  christos   int64_t top_then;
   3051      1.1  christos } larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
   3052      1.1  christos static size_t larch_reloc_queue_head = 0;
   3053      1.1  christos static size_t larch_reloc_queue_tail = 0;
   3054      1.1  christos 
   3055      1.1  christos static const char *
   3056      1.1  christos loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
   3057      1.1  christos 		    Elf_Internal_Sym *sym)
   3058      1.1  christos {
   3059      1.1  christos   const char *ret = NULL;
   3060      1.1  christos   if (sym)
   3061      1.1  christos     ret = bfd_elf_string_from_elf_section (input_bfd,
   3062      1.1  christos 					   elf_symtab_hdr (input_bfd).sh_link,
   3063      1.1  christos 					   sym->st_name);
   3064      1.1  christos   else if (h)
   3065      1.1  christos     ret = h->root.root.string;
   3066      1.1  christos 
   3067      1.1  christos   if (ret == NULL || *ret == '\0')
   3068      1.1  christos     ret = "<nameless>";
   3069      1.1  christos   return ret;
   3070      1.1  christos }
   3071      1.1  christos 
   3072      1.1  christos static void
   3073      1.1  christos loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
   3074      1.1  christos 			    bfd_vma r_offset, Elf_Internal_Sym *sym,
   3075      1.1  christos 			    struct elf_link_hash_entry *h, bfd_vma addend)
   3076      1.1  christos {
   3077      1.1  christos   if ((larch_reloc_queue_head == 0
   3078      1.1  christos        && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
   3079      1.1  christos       || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
   3080      1.1  christos     larch_reloc_queue_head =
   3081      1.1  christos       (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
   3082      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
   3083      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].section = section;
   3084      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
   3085      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
   3086      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
   3087      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].h = h;
   3088      1.1  christos   larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
   3089      1.1  christos   loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
   3090      1.1  christos   larch_reloc_queue_tail =
   3091      1.1  christos     (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
   3092      1.1  christos }
   3093      1.1  christos 
   3094      1.1  christos static void
   3095      1.1  christos loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
   3096      1.1  christos {
   3097      1.1  christos   size_t i = larch_reloc_queue_head;
   3098      1.1  christos   bfd *a_bfd = NULL;
   3099      1.1  christos   asection *section = NULL;
   3100      1.1  christos   bfd_vma r_offset = 0;
   3101      1.1  christos   int inited = 0;
   3102      1.1  christos   p ("Dump relocate record:\n");
   3103      1.1  christos   p ("stack top\t\trelocation name\t\tsymbol");
   3104      1.1  christos   while (i != larch_reloc_queue_tail)
   3105      1.1  christos     {
   3106      1.1  christos       if (a_bfd != larch_reloc_queue[i].bfd
   3107      1.1  christos 	  || section != larch_reloc_queue[i].section
   3108      1.1  christos 	  || r_offset != larch_reloc_queue[i].r_offset)
   3109      1.1  christos 	{
   3110      1.1  christos 	  a_bfd = larch_reloc_queue[i].bfd;
   3111      1.1  christos 	  section = larch_reloc_queue[i].section;
   3112      1.1  christos 	  r_offset = larch_reloc_queue[i].r_offset;
   3113      1.1  christos 	  p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
   3114      1.1  christos 	     larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
   3115      1.1  christos 	}
   3116      1.1  christos 
   3117      1.1  christos       if (!inited)
   3118      1.1  christos 	inited = 1, p ("...\n");
   3119      1.1  christos 
   3120      1.1  christos       reloc_howto_type *howto =
   3121      1.1  christos 	loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
   3122      1.1  christos 				      larch_reloc_queue[i].r_type);
   3123      1.1  christos       p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
   3124      1.1  christos 	 howto ? howto->name : "<unknown reloc>",
   3125      1.1  christos 	 loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
   3126      1.1  christos 			     larch_reloc_queue[i].sym));
   3127      1.1  christos 
   3128      1.1  christos       long addend = larch_reloc_queue[i].addend;
   3129      1.1  christos       if (addend < 0)
   3130      1.1  christos 	p (" - %ld", -addend);
   3131      1.1  christos       else if (0 < addend)
   3132      1.1  christos 	p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
   3133      1.1  christos 
   3134      1.1  christos       p ("\n");
   3135      1.1  christos       i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
   3136      1.1  christos     }
   3137      1.1  christos   p ("\n"
   3138      1.1  christos      "-- Record dump end --\n\n");
   3139      1.1  christos }
   3140      1.1  christos 
   3141      1.1  christos static bool
   3142      1.1  christos loongarch_reloc_is_fatal (struct bfd_link_info *info,
   3143      1.1  christos 			  bfd *input_bfd,
   3144      1.1  christos 			  asection *input_section,
   3145      1.1  christos 			  Elf_Internal_Rela *rel,
   3146      1.1  christos 			  reloc_howto_type *howto,
   3147      1.1  christos 			  bfd_reloc_status_type rtype,
   3148      1.1  christos 			  bool is_undefweak,
   3149      1.1  christos 			  const char *name,
   3150      1.1  christos 			  const char *msg)
   3151      1.1  christos {
   3152      1.1  christos   bool fatal = true;
   3153      1.1  christos   switch (rtype)
   3154      1.1  christos     {
   3155      1.1  christos       /* 'dangerous' means we do it but can't promise it's ok
   3156      1.1  christos 	 'unsupport' means out of ability of relocation type
   3157      1.1  christos 	 'undefined' means we can't deal with the undefined symbol.  */
   3158      1.1  christos     case bfd_reloc_undefined:
   3159      1.1  christos       info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
   3160      1.1  christos 					 rel->r_offset, true);
   3161      1.1  christos       info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
   3162      1.1  christos 			     input_bfd, input_section, rel->r_offset,
   3163      1.1  christos 			     howto->name,
   3164      1.1  christos 			     is_undefweak ? "[undefweak] " : "", name, msg);
   3165      1.1  christos       break;
   3166      1.1  christos     case bfd_reloc_dangerous:
   3167      1.1  christos       info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n",
   3168      1.1  christos 			     input_bfd, input_section, rel->r_offset,
   3169      1.1  christos 			     howto->name,
   3170      1.1  christos 			     is_undefweak ? "[undefweak] " : "", name, msg);
   3171      1.1  christos       fatal = false;
   3172      1.1  christos       break;
   3173      1.1  christos     case bfd_reloc_notsupported:
   3174      1.1  christos       info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n",
   3175      1.1  christos 			     input_bfd, input_section, rel->r_offset,
   3176      1.1  christos 			     howto->name,
   3177      1.1  christos 			     is_undefweak ? "[undefweak] " : "", name, msg);
   3178      1.1  christos       break;
   3179      1.1  christos     default:
   3180      1.1  christos       break;
   3181      1.1  christos     }
   3182      1.1  christos   return fatal;
   3183      1.1  christos }
   3184      1.1  christos 
   3185  1.1.1.2  christos /* If lo12 immediate > 0x7ff, because sign-extend caused by addi.d/ld.d,
   3186  1.1.1.2  christos    hi20 immediate need to add 0x1.
   3187  1.1.1.2  christos    For example: pc 0x120000000, symbol 0x120000812
   3188  1.1.1.2  christos    lo12 immediate is 0x812, 0x120000812 & 0xfff = 0x812
   3189  1.1.1.2  christos    hi20 immediate is 1, because lo12 imm > 0x7ff, symbol need to add 0x1000
   3190  1.1.1.2  christos    (((0x120000812 + 0x1000) & ~0xfff) - (0x120000000 & ~0xfff)) >> 12 = 0x1
   3191  1.1.1.2  christos 
   3192  1.1.1.2  christos    At run:
   3193  1.1.1.2  christos    pcalau12i $t0, hi20 (0x1)
   3194  1.1.1.2  christos       $t0 = 0x120000000 + (0x1 << 12) = 0x120001000
   3195  1.1.1.2  christos    addi.d $t0, $t0, lo12 (0x812)
   3196  1.1.1.2  christos       $t0 = 0x120001000 + 0xfffffffffffff812 (-(0x1000 - 0x812) = -0x7ee)
   3197  1.1.1.2  christos 	  = 0x120001000 - 0x7ee (0x1000 - 0x7ee = 0x812)
   3198  1.1.1.2  christos 	  = 0x120000812
   3199  1.1.1.2  christos     Without hi20 add 0x1000, the result 0x120000000 - 0x7ee = 0x11ffff812 is
   3200  1.1.1.2  christos     error.
   3201  1.1.1.2  christos     0x1000 + sign-extend-to64(0x8xx) = 0x8xx.  */
   3202  1.1.1.2  christos #define RELOCATE_CALC_PC32_HI20(relocation, pc) 	\
   3203  1.1.1.2  christos   ({							\
   3204  1.1.1.2  christos     bfd_vma __lo = (relocation) & ((bfd_vma)0xfff);	\
   3205  1.1.1.2  christos     relocation = (relocation & ~(bfd_vma)0xfff)		\
   3206  1.1.1.2  christos 		  - (pc & ~(bfd_vma)0xfff);		\
   3207  1.1.1.2  christos     if (__lo > 0x7ff)					\
   3208  1.1.1.2  christos 	relocation += 0x1000;				\
   3209  1.1.1.2  christos   })
   3210  1.1.1.2  christos 
   3211  1.1.1.2  christos /* Handle problems caused by symbol extensions in TLS LE, The processing
   3212  1.1.1.2  christos    is similar to the macro RELOCATE_CALC_PC32_HI20 method.  */
   3213  1.1.1.2  christos #define RELOCATE_TLS_TP32_HI20(relocation)		\
   3214  1.1.1.2  christos   ({							\
   3215  1.1.1.2  christos     bfd_vma __lo = (relocation) & ((bfd_vma)0xfff);	\
   3216  1.1.1.2  christos     if (__lo > 0x7ff)					\
   3217  1.1.1.2  christos 	relocation += 0x800;				\
   3218  1.1.1.2  christos     relocation = relocation & ~(bfd_vma)0xfff;		\
   3219  1.1.1.2  christos   })
   3220  1.1.1.2  christos 
   3221  1.1.1.2  christos /* For example: pc is 0x11000010000100, symbol is 0x1812348ffff812
   3222  1.1.1.2  christos    offset = (0x1812348ffff812 & ~0xfff) - (0x11000010000100 & ~0xfff)
   3223  1.1.1.2  christos 	  = 0x712347ffff000
   3224  1.1.1.2  christos    lo12: 0x1812348ffff812 & 0xfff = 0x812
   3225  1.1.1.2  christos    hi20: 0x7ffff + 0x1(lo12 > 0x7ff) = 0x80000
   3226  1.1.1.2  christos    lo20: 0x71234 - 0x1(lo12 > 0x7ff) + 0x1(hi20 > 0x7ffff)
   3227  1.1.1.2  christos    hi12: 0x0
   3228  1.1.1.2  christos 
   3229  1.1.1.2  christos    pcalau12i $t1, hi20 (0x80000)
   3230  1.1.1.2  christos       $t1 = 0x11000010000100 + sign-extend(0x80000 << 12)
   3231  1.1.1.2  christos 	  = 0x11000010000100 + 0xffffffff80000000
   3232  1.1.1.2  christos 	  = 0x10ffff90000000
   3233  1.1.1.2  christos    addi.d $t0, $zero, lo12 (0x812)
   3234  1.1.1.2  christos       $t0 = 0xfffffffffffff812 (if lo12 > 0x7ff, because sign-extend,
   3235  1.1.1.2  christos       lo20 need to sub 0x1)
   3236  1.1.1.2  christos    lu32i.d $t0, lo20 (0x71234)
   3237  1.1.1.2  christos       $t0 = {0x71234, 0xfffff812}
   3238  1.1.1.2  christos 	  = 0x71234fffff812
   3239  1.1.1.2  christos    lu52i.d $t0, hi12 (0x0)
   3240  1.1.1.2  christos       $t0 = {0x0, 0x71234fffff812}
   3241  1.1.1.2  christos 	  = 0x71234fffff812
   3242  1.1.1.2  christos    add.d $t1, $t1, $t0
   3243  1.1.1.2  christos       $t1 = 0x10ffff90000000 + 0x71234fffff812
   3244  1.1.1.2  christos 	  = 0x1812348ffff812.  */
   3245  1.1.1.2  christos #define RELOCATE_CALC_PC64_HI32(relocation, pc)  	\
   3246  1.1.1.2  christos   ({							\
   3247  1.1.1.2  christos     bfd_vma __lo = (relocation & (bfd_vma)0xfff);	\
   3248  1.1.1.2  christos     relocation = (relocation & ~(bfd_vma)0xfff)		\
   3249  1.1.1.2  christos 		  - ((pc) & ~(bfd_vma)0xfff);		\
   3250  1.1.1.2  christos     if (__lo > 0x7ff)					\
   3251  1.1.1.2  christos 	relocation += (0x1000 - 0x100000000);		\
   3252  1.1.1.2  christos     if (relocation & 0x80000000)			\
   3253  1.1.1.2  christos       relocation += 0x100000000;			\
   3254  1.1.1.2  christos   })
   3255  1.1.1.2  christos 
   3256      1.1  christos 
   3257  1.1.1.3  christos /* Compute the tp/dtp offset of a tls symbol.
   3258  1.1.1.3  christos    It is dtp offset in dynamic tls model (gd/ld) and tp
   3259  1.1.1.3  christos    offset in static tls model (ie/le). Both offsets are
   3260  1.1.1.3  christos    calculated the same way on LoongArch, so the same
   3261  1.1.1.3  christos    function is used.  */
   3262  1.1.1.3  christos static bfd_vma
   3263  1.1.1.3  christos tlsoff (struct bfd_link_info *info, bfd_vma addr)
   3264  1.1.1.3  christos {
   3265  1.1.1.3  christos   /* If tls_sec is NULL, we should have signalled an error already.  */
   3266  1.1.1.3  christos   if (elf_hash_table (info)->tls_sec == NULL)
   3267  1.1.1.3  christos     return 0;
   3268  1.1.1.3  christos   return addr - elf_hash_table (info)->tls_sec->vma;
   3269  1.1.1.2  christos }
   3270      1.1  christos 
   3271      1.1  christos static int
   3272      1.1  christos loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   3273      1.1  christos 				bfd *input_bfd, asection *input_section,
   3274      1.1  christos 				bfd_byte *contents, Elf_Internal_Rela *relocs,
   3275      1.1  christos 				Elf_Internal_Sym *local_syms,
   3276      1.1  christos 				asection **local_sections)
   3277      1.1  christos {
   3278      1.1  christos   Elf_Internal_Rela *rel;
   3279      1.1  christos   Elf_Internal_Rela *relend;
   3280      1.1  christos   bool fatal = false;
   3281      1.1  christos   asection *sreloc = elf_section_data (input_section)->sreloc;
   3282      1.1  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   3283      1.1  christos   Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
   3284      1.1  christos   struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
   3285      1.1  christos   bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
   3286      1.1  christos   bool is_pic = bfd_link_pic (info);
   3287      1.1  christos   bool is_dyn = elf_hash_table (info)->dynamic_sections_created;
   3288      1.1  christos   asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
   3289      1.1  christos   asection *got = htab->elf.sgot;
   3290      1.1  christos 
   3291      1.1  christos   relend = relocs + input_section->reloc_count;
   3292      1.1  christos   for (rel = relocs; rel < relend; rel++)
   3293      1.1  christos     {
   3294  1.1.1.2  christos       unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
   3295      1.1  christos       unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
   3296      1.1  christos       bfd_vma pc = sec_addr (input_section) + rel->r_offset;
   3297      1.1  christos       reloc_howto_type *howto = NULL;
   3298      1.1  christos       asection *sec = NULL;
   3299      1.1  christos       Elf_Internal_Sym *sym = NULL;
   3300      1.1  christos       struct elf_link_hash_entry *h = NULL;
   3301      1.1  christos       const char *name;
   3302      1.1  christos       bfd_reloc_status_type r = bfd_reloc_ok;
   3303  1.1.1.2  christos       bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
   3304      1.1  christos       bool resolved_local, resolved_dynly, resolved_to_const;
   3305      1.1  christos       char tls_type;
   3306  1.1.1.2  christos       bfd_vma relocation, off, ie_off, desc_off;
   3307      1.1  christos       int i, j;
   3308  1.1.1.3  christos       bool resolve_pcrel_undef_weak = false;
   3309      1.1  christos 
   3310  1.1.1.3  christos       /* When an unrecognized relocation is encountered, which usually
   3311  1.1.1.3  christos 	 occurs when using a newer assembler but an older linker, an error
   3312  1.1.1.3  christos 	 should be reported instead of continuing to the next relocation.  */
   3313      1.1  christos       howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
   3314  1.1.1.3  christos       if (howto == NULL)
   3315  1.1.1.3  christos 	return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
   3316  1.1.1.3  christos 
   3317  1.1.1.3  christos       if (r_type == R_LARCH_GNU_VTINHERIT || r_type == R_LARCH_GNU_VTENTRY)
   3318      1.1  christos 	continue;
   3319      1.1  christos 
   3320      1.1  christos       /* This is a final link.  */
   3321      1.1  christos       if (r_symndx < symtab_hdr->sh_info)
   3322      1.1  christos 	{
   3323      1.1  christos 	  is_undefweak = false;
   3324      1.1  christos 	  unresolved_reloc = false;
   3325      1.1  christos 	  sym = local_syms + r_symndx;
   3326      1.1  christos 	  sec = local_sections[r_symndx];
   3327      1.1  christos 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
   3328      1.1  christos 
   3329      1.1  christos 	  /* Relocate against local STT_GNU_IFUNC symbol.  */
   3330      1.1  christos 	  if (!bfd_link_relocatable (info)
   3331      1.1  christos 	      && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
   3332      1.1  christos 	    {
   3333      1.1  christos 	      h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
   3334      1.1  christos 						      false);
   3335      1.1  christos 	      if (h == NULL)
   3336      1.1  christos 		abort ();
   3337      1.1  christos 
   3338      1.1  christos 	      /* Set STT_GNU_IFUNC symbol value.  */
   3339      1.1  christos 	      h->root.u.def.value = sym->st_value;
   3340      1.1  christos 	      h->root.u.def.section = sec;
   3341      1.1  christos 	    }
   3342      1.1  christos 	  defined_local = true;
   3343      1.1  christos 	  resolved_local = true;
   3344      1.1  christos 	  resolved_dynly = false;
   3345      1.1  christos 	  resolved_to_const = false;
   3346  1.1.1.2  christos 
   3347  1.1.1.2  christos 	  /* Calc in funtion elf_link_input_bfd,
   3348  1.1.1.2  christos 	   * if #define elf_backend_rela_normal to 1.  */
   3349      1.1  christos 	  if (bfd_link_relocatable (info)
   3350      1.1  christos 	      && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
   3351  1.1.1.2  christos 	    continue;
   3352      1.1  christos 	}
   3353      1.1  christos       else
   3354      1.1  christos 	{
   3355      1.1  christos 	  bool warned, ignored;
   3356      1.1  christos 
   3357      1.1  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
   3358      1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
   3359      1.1  christos 				   h, sec, relocation,
   3360      1.1  christos 				   unresolved_reloc, warned, ignored);
   3361      1.1  christos 	  /* Here means symbol isn't local symbol only and 'h != NULL'.  */
   3362      1.1  christos 
   3363      1.1  christos 	  /* The 'unresolved_syms_in_objects' specify how to deal with undefined
   3364      1.1  christos 	     symbol.  And 'dynamic_undefined_weak' specify what to do when
   3365      1.1  christos 	     meeting undefweak.  */
   3366      1.1  christos 
   3367      1.1  christos 	  if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
   3368      1.1  christos 	    {
   3369      1.1  christos 	      defined_local = false;
   3370      1.1  christos 	      resolved_local = false;
   3371      1.1  christos 	      resolved_to_const = (!is_dyn || h->dynindx == -1
   3372      1.1  christos 				   || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
   3373      1.1  christos 	      resolved_dynly = !resolved_local && !resolved_to_const;
   3374      1.1  christos 	    }
   3375      1.1  christos 	  else if (warned)
   3376      1.1  christos 	    {
   3377      1.1  christos 	      /* Symbol undefined offen means failed already.  I don't know why
   3378      1.1  christos 		 'warned' here but I guess it want to continue relocating as if
   3379      1.1  christos 		 no error occures to find other errors as more as possible.  */
   3380      1.1  christos 
   3381      1.1  christos 	      /* To avoid generating warning messages about truncated
   3382      1.1  christos 		 relocations, set the relocation's address to be the same as
   3383      1.1  christos 		 the start of this section.  */
   3384      1.1  christos 	      relocation = (input_section->output_section
   3385      1.1  christos 			    ? input_section->output_section->vma
   3386      1.1  christos 			    : 0);
   3387      1.1  christos 
   3388      1.1  christos 	      defined_local = relocation != 0;
   3389      1.1  christos 	      resolved_local = defined_local;
   3390      1.1  christos 	      resolved_to_const = !resolved_local;
   3391      1.1  christos 	      resolved_dynly = false;
   3392      1.1  christos 	    }
   3393      1.1  christos 	  else
   3394      1.1  christos 	    {
   3395      1.1  christos 	      defined_local = !unresolved_reloc && !ignored;
   3396      1.1  christos 	      resolved_local =
   3397  1.1.1.3  christos 		defined_local && LARCH_REF_LOCAL (info, h);
   3398      1.1  christos 	      resolved_dynly = !resolved_local;
   3399      1.1  christos 	      resolved_to_const = !resolved_local && !resolved_dynly;
   3400      1.1  christos 	    }
   3401      1.1  christos 	}
   3402      1.1  christos 
   3403      1.1  christos       name = loongarch_sym_name (input_bfd, h, sym);
   3404      1.1  christos 
   3405      1.1  christos       if (sec != NULL && discarded_section (sec))
   3406      1.1  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
   3407      1.1  christos 					 1, relend, howto, 0, contents);
   3408      1.1  christos 
   3409      1.1  christos       if (bfd_link_relocatable (info))
   3410      1.1  christos 	continue;
   3411      1.1  christos 
   3412      1.1  christos       /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
   3413      1.1  christos 	 from removed linkonce sections, or sections discarded by a linker
   3414      1.1  christos 	 script.  Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const.  */
   3415  1.1.1.3  christos       if (r_symndx == STN_UNDEF)
   3416      1.1  christos 	{
   3417      1.1  christos 	  defined_local = false;
   3418      1.1  christos 	  resolved_local = false;
   3419      1.1  christos 	  resolved_dynly = false;
   3420      1.1  christos 	  resolved_to_const = true;
   3421      1.1  christos 	}
   3422      1.1  christos 
   3423  1.1.1.2  christos       /* The ifunc reference generate plt.  */
   3424      1.1  christos       if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE)
   3425      1.1  christos 	{
   3426      1.1  christos 	  defined_local = true;
   3427      1.1  christos 	  resolved_local = true;
   3428      1.1  christos 	  resolved_dynly = false;
   3429      1.1  christos 	  resolved_to_const = false;
   3430      1.1  christos 	  relocation = sec_addr (plt) + h->plt.offset;
   3431      1.1  christos 	}
   3432      1.1  christos 
   3433      1.1  christos       unresolved_reloc = resolved_dynly;
   3434      1.1  christos 
   3435      1.1  christos       BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
   3436      1.1  christos 
   3437      1.1  christos       /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));.  */
   3438      1.1  christos 
   3439      1.1  christos       BFD_ASSERT (!resolved_local || defined_local);
   3440      1.1  christos 
   3441  1.1.1.2  christos       is_desc = false;
   3442      1.1  christos       is_ie = false;
   3443      1.1  christos       switch (r_type)
   3444      1.1  christos 	{
   3445      1.1  christos 	case R_LARCH_MARK_PCREL:
   3446      1.1  christos 	case R_LARCH_MARK_LA:
   3447      1.1  christos 	case R_LARCH_NONE:
   3448      1.1  christos 	  r = bfd_reloc_continue;
   3449      1.1  christos 	  unresolved_reloc = false;
   3450      1.1  christos 	  break;
   3451      1.1  christos 
   3452      1.1  christos 	case R_LARCH_32:
   3453      1.1  christos 	case R_LARCH_64:
   3454      1.1  christos 	  if (resolved_dynly || (is_pic && resolved_local))
   3455      1.1  christos 	    {
   3456      1.1  christos 	      Elf_Internal_Rela outrel;
   3457      1.1  christos 
   3458      1.1  christos 	      /* When generating a shared object, these relocations are copied
   3459      1.1  christos 		 into the output file to be resolved at run time.  */
   3460      1.1  christos 
   3461      1.1  christos 	      outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
   3462      1.1  christos 							 input_section,
   3463      1.1  christos 							 rel->r_offset);
   3464      1.1  christos 
   3465      1.1  christos 	      unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
   3466      1.1  christos 				  && (input_section->flags & SEC_ALLOC));
   3467      1.1  christos 
   3468      1.1  christos 	      outrel.r_offset += sec_addr (input_section);
   3469      1.1  christos 
   3470  1.1.1.2  christos 	      /* A pointer point to a ifunc symbol.  */
   3471  1.1.1.2  christos 	      if (h && h->type == STT_GNU_IFUNC)
   3472  1.1.1.2  christos 		{
   3473  1.1.1.2  christos 		  if (h->dynindx == -1)
   3474  1.1.1.2  christos 		    {
   3475  1.1.1.2  christos 		      outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
   3476  1.1.1.2  christos 		      outrel.r_addend = (h->root.u.def.value
   3477  1.1.1.2  christos 				  + h->root.u.def.section->output_section->vma
   3478  1.1.1.2  christos 				  + h->root.u.def.section->output_offset);
   3479  1.1.1.2  christos 		    }
   3480  1.1.1.2  christos 		  else
   3481  1.1.1.2  christos 		    {
   3482  1.1.1.2  christos 		      outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
   3483  1.1.1.2  christos 		      outrel.r_addend = 0;
   3484  1.1.1.2  christos 		    }
   3485  1.1.1.2  christos 
   3486  1.1.1.3  christos 		  if (LARCH_REF_LOCAL (info, h))
   3487  1.1.1.2  christos 		    {
   3488  1.1.1.2  christos 
   3489  1.1.1.2  christos 		      if (htab->elf.splt != NULL)
   3490  1.1.1.2  christos 			sreloc = htab->elf.srelgot;
   3491  1.1.1.2  christos 		      else
   3492  1.1.1.2  christos 			sreloc = htab->elf.irelplt;
   3493  1.1.1.2  christos 		    }
   3494      1.1  christos 		  else
   3495  1.1.1.2  christos 		    {
   3496  1.1.1.2  christos 
   3497  1.1.1.2  christos 		      if (bfd_link_pic (info))
   3498  1.1.1.2  christos 			sreloc = htab->elf.irelifunc;
   3499  1.1.1.2  christos 		      else if (htab->elf.splt != NULL)
   3500  1.1.1.2  christos 			sreloc = htab->elf.srelgot;
   3501  1.1.1.2  christos 		      else
   3502  1.1.1.2  christos 			sreloc = htab->elf.irelplt;
   3503  1.1.1.2  christos 		    }
   3504      1.1  christos 		}
   3505      1.1  christos 	      else if (resolved_dynly)
   3506      1.1  christos 		{
   3507  1.1.1.2  christos 		  if (h->dynindx == -1)
   3508  1.1.1.3  christos 		    outrel.r_info = ELFNN_R_INFO (0, r_type);
   3509  1.1.1.2  christos 		  else
   3510  1.1.1.2  christos 		    outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
   3511  1.1.1.2  christos 
   3512      1.1  christos 		  outrel.r_addend = rel->r_addend;
   3513      1.1  christos 		}
   3514      1.1  christos 	      else
   3515      1.1  christos 		{
   3516      1.1  christos 		  outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
   3517      1.1  christos 		  outrel.r_addend = relocation + rel->r_addend;
   3518      1.1  christos 		}
   3519      1.1  christos 
   3520  1.1.1.3  christos 	      /* No alloc space of func allocate_dynrelocs.
   3521  1.1.1.3  christos 		 No alloc space of invalid R_LARCH_32 in ELFCLASS64.  */
   3522  1.1.1.2  christos 	      if (unresolved_reloc
   3523  1.1.1.3  christos 		  && (ARCH_SIZE == 32 || r_type != R_LARCH_32)
   3524  1.1.1.2  christos 		  && !(h && (h->is_weakalias || !h->dyn_relocs)))
   3525  1.1.1.3  christos 		{
   3526  1.1.1.3  christos 		  if (info->enable_dt_relr
   3527  1.1.1.3  christos 		      && (ELFNN_R_TYPE (outrel.r_info) == R_LARCH_RELATIVE)
   3528  1.1.1.3  christos 		      && input_section->alignment_power != 0
   3529  1.1.1.3  christos 		      && rel->r_offset % 2 == 0)
   3530  1.1.1.3  christos 		    /* Don't emit a relative relocation that is packed,
   3531  1.1.1.3  christos 		       only apply the addend (as if we are applying the
   3532  1.1.1.3  christos 		       original R_LARCH_NN reloc in a PDE).  */
   3533  1.1.1.3  christos 		    r = perform_relocation (rel, input_section, howto,
   3534  1.1.1.3  christos 					    relocation, input_bfd,
   3535  1.1.1.3  christos 					    contents);
   3536  1.1.1.3  christos 		  else
   3537  1.1.1.3  christos 		    loongarch_elf_append_rela (output_bfd, sreloc,
   3538  1.1.1.3  christos 					       &outrel);
   3539  1.1.1.3  christos 		}
   3540      1.1  christos 	    }
   3541      1.1  christos 
   3542      1.1  christos 	  relocation += rel->r_addend;
   3543      1.1  christos 	  break;
   3544      1.1  christos 
   3545  1.1.1.2  christos 	case R_LARCH_ADD6:
   3546      1.1  christos 	case R_LARCH_ADD8:
   3547      1.1  christos 	case R_LARCH_ADD16:
   3548      1.1  christos 	case R_LARCH_ADD24:
   3549      1.1  christos 	case R_LARCH_ADD32:
   3550      1.1  christos 	case R_LARCH_ADD64:
   3551  1.1.1.2  christos 	  {
   3552  1.1.1.2  christos 	    bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
   3553  1.1.1.2  christos 					 contents + rel->r_offset);
   3554  1.1.1.2  christos 	    relocation = old_value + relocation + rel->r_addend;
   3555  1.1.1.2  christos 	    break;
   3556  1.1.1.2  christos 	  }
   3557  1.1.1.2  christos 
   3558  1.1.1.2  christos 	case R_LARCH_SUB6:
   3559      1.1  christos 	case R_LARCH_SUB8:
   3560      1.1  christos 	case R_LARCH_SUB16:
   3561      1.1  christos 	case R_LARCH_SUB24:
   3562      1.1  christos 	case R_LARCH_SUB32:
   3563      1.1  christos 	case R_LARCH_SUB64:
   3564  1.1.1.2  christos 	  {
   3565  1.1.1.2  christos 	    bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
   3566  1.1.1.2  christos 					  contents + rel->r_offset);
   3567  1.1.1.2  christos 	    relocation = old_value - relocation - rel->r_addend;
   3568  1.1.1.2  christos 	    break;
   3569  1.1.1.2  christos 	  }
   3570  1.1.1.2  christos 
   3571  1.1.1.2  christos 	case R_LARCH_ADD_ULEB128:
   3572  1.1.1.2  christos 	case R_LARCH_SUB_ULEB128:
   3573  1.1.1.2  christos 	  {
   3574  1.1.1.2  christos 	    /* Get the value and length of the uleb128 data.  */
   3575  1.1.1.2  christos 	    unsigned int len = 0;
   3576  1.1.1.2  christos 	    bfd_vma old_value = _bfd_read_unsigned_leb128 (input_bfd,
   3577  1.1.1.2  christos 				    contents + rel->r_offset, &len);
   3578  1.1.1.2  christos 
   3579  1.1.1.2  christos 	    if (R_LARCH_ADD_ULEB128 == ELFNN_R_TYPE (rel->r_info))
   3580  1.1.1.2  christos 	      relocation = old_value + relocation + rel->r_addend;
   3581  1.1.1.2  christos 	    else if (R_LARCH_SUB_ULEB128 == ELFNN_R_TYPE (rel->r_info))
   3582  1.1.1.2  christos 	      relocation = old_value - relocation - rel->r_addend;
   3583  1.1.1.2  christos 
   3584  1.1.1.2  christos 	    bfd_vma mask = (1 << (7 * len)) - 1;
   3585  1.1.1.2  christos 	    relocation &= mask;
   3586  1.1.1.2  christos 	    break;
   3587  1.1.1.2  christos 	  }
   3588      1.1  christos 
   3589      1.1  christos 	case R_LARCH_TLS_DTPREL32:
   3590      1.1  christos 	case R_LARCH_TLS_DTPREL64:
   3591      1.1  christos 	  if (resolved_dynly)
   3592      1.1  christos 	    {
   3593      1.1  christos 	      Elf_Internal_Rela outrel;
   3594      1.1  christos 
   3595      1.1  christos 	      outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
   3596      1.1  christos 							 input_section,
   3597      1.1  christos 							 rel->r_offset);
   3598      1.1  christos 	      unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
   3599      1.1  christos 				  && (input_section->flags & SEC_ALLOC));
   3600      1.1  christos 	      outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
   3601      1.1  christos 	      outrel.r_offset += sec_addr (input_section);
   3602      1.1  christos 	      outrel.r_addend = rel->r_addend;
   3603      1.1  christos 	      if (unresolved_reloc)
   3604      1.1  christos 		loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
   3605      1.1  christos 	      break;
   3606      1.1  christos 	    }
   3607      1.1  christos 
   3608      1.1  christos 	  if (resolved_to_const)
   3609      1.1  christos 	    fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
   3610      1.1  christos 					      rel, howto,
   3611      1.1  christos 					      bfd_reloc_notsupported,
   3612      1.1  christos 					      is_undefweak, name,
   3613      1.1  christos 					      "Internal:");
   3614      1.1  christos 	  if (resolved_local)
   3615      1.1  christos 	    {
   3616      1.1  christos 	      if (!elf_hash_table (info)->tls_sec)
   3617      1.1  christos 		{
   3618      1.1  christos 		fatal = loongarch_reloc_is_fatal (info, input_bfd,
   3619      1.1  christos 			  input_section, rel, howto, bfd_reloc_notsupported,
   3620      1.1  christos 			  is_undefweak, name, "TLS section not be created");
   3621      1.1  christos 		}
   3622      1.1  christos 	      else
   3623  1.1.1.3  christos 		relocation = tlsoff (info, relocation);
   3624      1.1  christos 	    }
   3625      1.1  christos 	  else
   3626      1.1  christos 	    {
   3627      1.1  christos 	    fatal = loongarch_reloc_is_fatal (info, input_bfd,
   3628      1.1  christos 		      input_section, rel, howto, bfd_reloc_undefined,
   3629      1.1  christos 		      is_undefweak, name,
   3630      1.1  christos 		      "TLS LE just can be resolved local only.");
   3631      1.1  christos 	    }
   3632      1.1  christos 
   3633      1.1  christos 	  break;
   3634      1.1  christos 
   3635      1.1  christos 	case R_LARCH_SOP_PUSH_TLS_TPREL:
   3636      1.1  christos 	  if (resolved_local)
   3637      1.1  christos 	    {
   3638      1.1  christos 	      if (!elf_hash_table (info)->tls_sec)
   3639      1.1  christos 		fatal = (loongarch_reloc_is_fatal
   3640      1.1  christos 			 (info, input_bfd, input_section, rel, howto,
   3641      1.1  christos 			  bfd_reloc_notsupported, is_undefweak, name,
   3642      1.1  christos 			  "TLS section not be created"));
   3643      1.1  christos 	      else
   3644  1.1.1.3  christos 		relocation = tlsoff (info, relocation);
   3645      1.1  christos 	    }
   3646      1.1  christos 	  else
   3647      1.1  christos 	    fatal = (loongarch_reloc_is_fatal
   3648      1.1  christos 		     (info, input_bfd, input_section, rel, howto,
   3649      1.1  christos 		      bfd_reloc_undefined, is_undefweak, name,
   3650      1.1  christos 		      "TLS LE just can be resolved local only."));
   3651      1.1  christos 	  break;
   3652      1.1  christos 
   3653      1.1  christos 	case R_LARCH_SOP_PUSH_ABSOLUTE:
   3654      1.1  christos 	  if (is_undefweak)
   3655      1.1  christos 	    {
   3656      1.1  christos 	      if (resolved_dynly)
   3657      1.1  christos 		fatal = (loongarch_reloc_is_fatal
   3658      1.1  christos 			 (info, input_bfd, input_section, rel, howto,
   3659      1.1  christos 			  bfd_reloc_dangerous, is_undefweak, name,
   3660      1.1  christos 			  "Someone require us to resolve undefweak "
   3661      1.1  christos 			  "symbol dynamically.  \n"
   3662      1.1  christos 			  "But this reloc can't be done.  "
   3663      1.1  christos 			  "I think I can't throw error "
   3664      1.1  christos 			  "for this\n"
   3665      1.1  christos 			  "so I resolved it to 0.  "
   3666      1.1  christos 			  "I suggest to re-compile with '-fpic'."));
   3667      1.1  christos 
   3668      1.1  christos 	      relocation = 0;
   3669      1.1  christos 	      unresolved_reloc = false;
   3670      1.1  christos 	      break;
   3671      1.1  christos 	    }
   3672      1.1  christos 
   3673      1.1  christos 	  if (resolved_to_const)
   3674      1.1  christos 	    {
   3675      1.1  christos 	      relocation += rel->r_addend;
   3676      1.1  christos 	      break;
   3677      1.1  christos 	    }
   3678      1.1  christos 
   3679      1.1  christos 	  if (is_pic)
   3680      1.1  christos 	    {
   3681      1.1  christos 	      fatal = (loongarch_reloc_is_fatal
   3682      1.1  christos 		       (info, input_bfd, input_section, rel, howto,
   3683      1.1  christos 			bfd_reloc_notsupported, is_undefweak, name,
   3684      1.1  christos 			"Under PIC we don't know load address.  Re-compile "
   3685      1.1  christos 			"with '-fpic'?"));
   3686      1.1  christos 	      break;
   3687      1.1  christos 	    }
   3688      1.1  christos 
   3689      1.1  christos 	  if (resolved_dynly)
   3690      1.1  christos 	    {
   3691      1.1  christos 	      if (!(plt && h && h->plt.offset != MINUS_ONE))
   3692      1.1  christos 		{
   3693      1.1  christos 		  fatal = (loongarch_reloc_is_fatal
   3694      1.1  christos 			   (info, input_bfd, input_section, rel, howto,
   3695      1.1  christos 			    bfd_reloc_undefined, is_undefweak, name,
   3696      1.1  christos 			    "Can't be resolved dynamically.  Try to re-compile "
   3697      1.1  christos 			    "with '-fpic'?"));
   3698      1.1  christos 		  break;
   3699      1.1  christos 		}
   3700      1.1  christos 
   3701      1.1  christos 	      if (rel->r_addend != 0)
   3702      1.1  christos 		{
   3703      1.1  christos 		  fatal = (loongarch_reloc_is_fatal
   3704      1.1  christos 			   (info, input_bfd, input_section, rel, howto,
   3705      1.1  christos 			    bfd_reloc_notsupported, is_undefweak, name,
   3706      1.1  christos 			    "Shouldn't be with r_addend."));
   3707      1.1  christos 		  break;
   3708      1.1  christos 		}
   3709      1.1  christos 
   3710      1.1  christos 	      relocation = sec_addr (plt) + h->plt.offset;
   3711      1.1  christos 	      unresolved_reloc = false;
   3712      1.1  christos 	      break;
   3713      1.1  christos 	    }
   3714      1.1  christos 
   3715      1.1  christos 	  if (resolved_local)
   3716      1.1  christos 	    {
   3717      1.1  christos 	      relocation += rel->r_addend;
   3718      1.1  christos 	      break;
   3719      1.1  christos 	    }
   3720      1.1  christos 
   3721      1.1  christos 	  break;
   3722      1.1  christos 
   3723      1.1  christos 	case R_LARCH_SOP_PUSH_PCREL:
   3724      1.1  christos 	case R_LARCH_SOP_PUSH_PLT_PCREL:
   3725      1.1  christos 	  unresolved_reloc = false;
   3726      1.1  christos 
   3727  1.1.1.2  christos 	  if (is_undefweak)
   3728      1.1  christos 	    {
   3729      1.1  christos 	      i = 0, j = 0;
   3730      1.1  christos 	      relocation = 0;
   3731      1.1  christos 	      if (resolved_dynly)
   3732      1.1  christos 		{
   3733      1.1  christos 		  if (h && h->plt.offset != MINUS_ONE)
   3734      1.1  christos 		    i = 1, j = 2;
   3735      1.1  christos 		  else
   3736      1.1  christos 		    fatal = (loongarch_reloc_is_fatal
   3737      1.1  christos 			     (info, input_bfd, input_section, rel, howto,
   3738      1.1  christos 			      bfd_reloc_dangerous, is_undefweak, name,
   3739      1.1  christos 			      "Undefweak need to be resolved dynamically, "
   3740      1.1  christos 			      "but PLT stub doesn't represent."));
   3741      1.1  christos 		}
   3742      1.1  christos 	    }
   3743      1.1  christos 	  else
   3744      1.1  christos 	    {
   3745      1.1  christos 	      if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
   3746      1.1  christos 		{
   3747      1.1  christos 		  fatal = (loongarch_reloc_is_fatal
   3748      1.1  christos 			   (info, input_bfd, input_section, rel, howto,
   3749      1.1  christos 			    bfd_reloc_undefined, is_undefweak, name,
   3750      1.1  christos 			    "PLT stub does not represent and "
   3751      1.1  christos 			    "symbol not defined."));
   3752      1.1  christos 		  break;
   3753      1.1  christos 		}
   3754      1.1  christos 
   3755      1.1  christos 	      if (resolved_local)
   3756      1.1  christos 		i = 0, j = 2;
   3757      1.1  christos 	      else /* if (resolved_dynly) */
   3758      1.1  christos 		{
   3759      1.1  christos 		  if (!(h && h->plt.offset != MINUS_ONE))
   3760      1.1  christos 		    fatal = (loongarch_reloc_is_fatal
   3761      1.1  christos 			     (info, input_bfd, input_section, rel, howto,
   3762      1.1  christos 			      bfd_reloc_dangerous, is_undefweak, name,
   3763      1.1  christos 			      "Internal: PLT stub doesn't represent.  "
   3764      1.1  christos 			      "Resolve it with pcrel"));
   3765      1.1  christos 		  i = 1, j = 3;
   3766      1.1  christos 		}
   3767      1.1  christos 	    }
   3768      1.1  christos 
   3769      1.1  christos 	  for (; i < j; i++)
   3770      1.1  christos 	    {
   3771      1.1  christos 	      if ((i & 1) == 0 && defined_local)
   3772      1.1  christos 		{
   3773      1.1  christos 		  relocation -= pc;
   3774      1.1  christos 		  relocation += rel->r_addend;
   3775      1.1  christos 		  break;
   3776      1.1  christos 		}
   3777      1.1  christos 
   3778      1.1  christos 	      if ((i & 1) && h && h->plt.offset != MINUS_ONE)
   3779      1.1  christos 		{
   3780      1.1  christos 		  if (rel->r_addend != 0)
   3781      1.1  christos 		    {
   3782      1.1  christos 		      fatal = (loongarch_reloc_is_fatal
   3783      1.1  christos 			       (info, input_bfd, input_section, rel, howto,
   3784      1.1  christos 				bfd_reloc_notsupported, is_undefweak, name,
   3785      1.1  christos 				"PLT shouldn't be with r_addend."));
   3786      1.1  christos 		      break;
   3787      1.1  christos 		    }
   3788      1.1  christos 		  relocation = sec_addr (plt) + h->plt.offset - pc;
   3789      1.1  christos 		  break;
   3790      1.1  christos 		}
   3791      1.1  christos 	    }
   3792      1.1  christos 	  break;
   3793      1.1  christos 
   3794      1.1  christos 	case R_LARCH_SOP_PUSH_GPREL:
   3795      1.1  christos 	  unresolved_reloc = false;
   3796      1.1  christos 
   3797      1.1  christos 	  if (rel->r_addend != 0)
   3798      1.1  christos 	    {
   3799      1.1  christos 	      fatal = (loongarch_reloc_is_fatal
   3800      1.1  christos 		       (info, input_bfd, input_section, rel, howto,
   3801      1.1  christos 			bfd_reloc_notsupported, is_undefweak, name,
   3802      1.1  christos 			"Shouldn't be with r_addend."));
   3803      1.1  christos 	      break;
   3804      1.1  christos 	    }
   3805      1.1  christos 
   3806      1.1  christos 	  if (h != NULL)
   3807      1.1  christos 	    {
   3808  1.1.1.2  christos 	      off = h->got.offset & (~1);
   3809      1.1  christos 
   3810  1.1.1.2  christos 	      if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC)
   3811      1.1  christos 		{
   3812      1.1  christos 		  fatal = (loongarch_reloc_is_fatal
   3813      1.1  christos 			   (info, input_bfd, input_section, rel, howto,
   3814      1.1  christos 			    bfd_reloc_notsupported, is_undefweak, name,
   3815      1.1  christos 			    "Internal: GOT entry doesn't represent."));
   3816      1.1  christos 		  break;
   3817      1.1  christos 		}
   3818      1.1  christos 
   3819      1.1  christos 	      /* Hidden symbol not has .got entry, only .got.plt entry
   3820      1.1  christos 		 so gprel is (plt - got).  */
   3821  1.1.1.2  christos 	      if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
   3822      1.1  christos 		{
   3823      1.1  christos 		  if (h->plt.offset == (bfd_vma) -1)
   3824      1.1  christos 		    {
   3825      1.1  christos 		      abort();
   3826      1.1  christos 		    }
   3827      1.1  christos 
   3828      1.1  christos 		  bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE;
   3829      1.1  christos 		  off = plt_index * GOT_ENTRY_SIZE;
   3830      1.1  christos 
   3831      1.1  christos 		  if (htab->elf.splt != NULL)
   3832      1.1  christos 		    {
   3833      1.1  christos 		      /* Section .plt header is 2 times of plt entry.  */
   3834  1.1.1.2  christos 		      off = sec_addr (htab->elf.sgotplt) + off
   3835  1.1.1.2  christos 			- sec_addr (htab->elf.sgot);
   3836      1.1  christos 		    }
   3837      1.1  christos 		  else
   3838      1.1  christos 		    {
   3839      1.1  christos 		      /* Section iplt not has plt header.  */
   3840  1.1.1.2  christos 		      off = sec_addr (htab->elf.igotplt) + off
   3841  1.1.1.2  christos 			- sec_addr (htab->elf.sgot);
   3842      1.1  christos 		    }
   3843      1.1  christos 		}
   3844      1.1  christos 
   3845  1.1.1.2  christos 	      if ((h->got.offset & 1) == 0)
   3846      1.1  christos 		{
   3847  1.1.1.2  christos 		  if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
   3848  1.1.1.2  christos 							bfd_link_pic (info), h)
   3849  1.1.1.2  christos 		      && ((bfd_link_pic (info)
   3850  1.1.1.3  christos 			   && LARCH_REF_LOCAL (info, h))))
   3851      1.1  christos 		    {
   3852  1.1.1.2  christos 		      /* This is actually a static link, or it is a
   3853  1.1.1.2  christos 			 -Bsymbolic link and the symbol is defined
   3854  1.1.1.2  christos 			 locally, or the symbol was forced to be local
   3855  1.1.1.2  christos 			 because of a version file.  We must initialize
   3856  1.1.1.2  christos 			 this entry in the global offset table.  Since the
   3857  1.1.1.2  christos 			 offset must always be a multiple of the word size,
   3858  1.1.1.2  christos 			 we use the least significant bit to record whether
   3859  1.1.1.2  christos 			 we have initialized it already.
   3860  1.1.1.2  christos 
   3861  1.1.1.2  christos 			 When doing a dynamic link, we create a rela.got
   3862  1.1.1.2  christos 			 relocation entry to initialize the value.  This
   3863  1.1.1.2  christos 			 is done in the finish_dynamic_symbol routine.  */
   3864      1.1  christos 
   3865  1.1.1.2  christos 		      if (resolved_dynly)
   3866  1.1.1.2  christos 			{
   3867  1.1.1.2  christos 			  fatal = (loongarch_reloc_is_fatal
   3868  1.1.1.2  christos 				   (info, input_bfd, input_section, rel, howto,
   3869  1.1.1.2  christos 				    bfd_reloc_dangerous, is_undefweak, name,
   3870  1.1.1.2  christos 				    "Internal: here shouldn't dynamic."));
   3871  1.1.1.2  christos 			}
   3872      1.1  christos 
   3873  1.1.1.2  christos 		      if (!(defined_local || resolved_to_const))
   3874      1.1  christos 			{
   3875  1.1.1.2  christos 			  fatal = (loongarch_reloc_is_fatal
   3876  1.1.1.2  christos 				   (info, input_bfd, input_section, rel, howto,
   3877  1.1.1.2  christos 				    bfd_reloc_undefined, is_undefweak, name,
   3878  1.1.1.2  christos 				    "Internal: "));
   3879  1.1.1.2  christos 			  break;
   3880      1.1  christos 			}
   3881  1.1.1.2  christos 
   3882  1.1.1.2  christos 		      asection *s;
   3883  1.1.1.2  christos 		      Elf_Internal_Rela outrel;
   3884  1.1.1.2  christos 		      /* We need to generate a R_LARCH_RELATIVE reloc
   3885  1.1.1.2  christos 			 for the dynamic linker.  */
   3886  1.1.1.2  christos 		      s = htab->elf.srelgot;
   3887  1.1.1.2  christos 		      if (!s)
   3888  1.1.1.2  christos 			{
   3889  1.1.1.2  christos 			  fatal = loongarch_reloc_is_fatal
   3890  1.1.1.2  christos 			    (info, input_bfd,
   3891  1.1.1.2  christos 			     input_section, rel, howto,
   3892  1.1.1.2  christos 			     bfd_reloc_notsupported, is_undefweak, name,
   3893  1.1.1.2  christos 			     "Internal: '.rel.got' not represent");
   3894  1.1.1.2  christos 			  break;
   3895  1.1.1.2  christos 			}
   3896  1.1.1.2  christos 
   3897  1.1.1.2  christos 		      outrel.r_offset = sec_addr (got) + off;
   3898  1.1.1.2  christos 		      outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
   3899  1.1.1.2  christos 		      outrel.r_addend = relocation; /* Link-time addr.  */
   3900  1.1.1.2  christos 		      loongarch_elf_append_rela (output_bfd, s, &outrel);
   3901      1.1  christos 		    }
   3902  1.1.1.2  christos 		  bfd_put_NN (output_bfd, relocation, got->contents + off);
   3903  1.1.1.2  christos 		  h->got.offset |= 1;
   3904      1.1  christos 		}
   3905      1.1  christos 	    }
   3906      1.1  christos 	  else
   3907      1.1  christos 	    {
   3908      1.1  christos 	      if (!local_got_offsets)
   3909      1.1  christos 		{
   3910      1.1  christos 		  fatal = (loongarch_reloc_is_fatal
   3911      1.1  christos 			   (info, input_bfd, input_section, rel, howto,
   3912      1.1  christos 			    bfd_reloc_notsupported, is_undefweak, name,
   3913      1.1  christos 			    "Internal: local got offsets not reporesent."));
   3914      1.1  christos 		  break;
   3915      1.1  christos 		}
   3916      1.1  christos 
   3917  1.1.1.2  christos 	      off = local_got_offsets[r_symndx] & (~1);
   3918      1.1  christos 
   3919  1.1.1.2  christos 	      if (local_got_offsets[r_symndx] == MINUS_ONE)
   3920      1.1  christos 		{
   3921      1.1  christos 		  fatal = (loongarch_reloc_is_fatal
   3922      1.1  christos 			   (info, input_bfd, input_section, rel, howto,
   3923      1.1  christos 			    bfd_reloc_notsupported, is_undefweak, name,
   3924      1.1  christos 			    "Internal: GOT entry doesn't represent."));
   3925      1.1  christos 		  break;
   3926      1.1  christos 		}
   3927      1.1  christos 
   3928      1.1  christos 	      /* The offset must always be a multiple of the word size.
   3929      1.1  christos 		 So, we can use the least significant bit to record
   3930      1.1  christos 		 whether we have already processed this entry.  */
   3931  1.1.1.2  christos 	      if ((local_got_offsets[r_symndx] & 1) == 0)
   3932      1.1  christos 		{
   3933      1.1  christos 		  if (is_pic)
   3934      1.1  christos 		    {
   3935      1.1  christos 		      asection *s;
   3936      1.1  christos 		      Elf_Internal_Rela outrel;
   3937      1.1  christos 		      /* We need to generate a R_LARCH_RELATIVE reloc
   3938      1.1  christos 			 for the dynamic linker.  */
   3939      1.1  christos 		      s = htab->elf.srelgot;
   3940      1.1  christos 		      if (!s)
   3941      1.1  christos 			{
   3942      1.1  christos 			  fatal = (loongarch_reloc_is_fatal
   3943      1.1  christos 				   (info, input_bfd, input_section, rel, howto,
   3944      1.1  christos 				    bfd_reloc_notsupported, is_undefweak, name,
   3945      1.1  christos 				    "Internal: '.rel.got' not represent"));
   3946      1.1  christos 			  break;
   3947      1.1  christos 			}
   3948      1.1  christos 
   3949      1.1  christos 		      outrel.r_offset = sec_addr (got) + off;
   3950      1.1  christos 		      outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
   3951      1.1  christos 		      outrel.r_addend = relocation; /* Link-time addr.  */
   3952      1.1  christos 		      loongarch_elf_append_rela (output_bfd, s, &outrel);
   3953      1.1  christos 		    }
   3954      1.1  christos 
   3955      1.1  christos 		  bfd_put_NN (output_bfd, relocation, got->contents + off);
   3956      1.1  christos 		  local_got_offsets[r_symndx] |= 1;
   3957      1.1  christos 		}
   3958      1.1  christos 	    }
   3959      1.1  christos 	  relocation = off;
   3960  1.1.1.2  christos 
   3961      1.1  christos 	  break;
   3962      1.1  christos 
   3963      1.1  christos 	case R_LARCH_SOP_PUSH_TLS_GOT:
   3964      1.1  christos 	case R_LARCH_SOP_PUSH_TLS_GD:
   3965  1.1.1.2  christos 	  {
   3966  1.1.1.2  christos 	    unresolved_reloc = false;
   3967  1.1.1.2  christos 	    if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
   3968  1.1.1.2  christos 	      is_ie = true;
   3969  1.1.1.2  christos 
   3970  1.1.1.2  christos 	    bfd_vma got_off = 0;
   3971  1.1.1.2  christos 	    if (h != NULL)
   3972  1.1.1.2  christos 	      {
   3973  1.1.1.2  christos 		got_off = h->got.offset;
   3974  1.1.1.2  christos 		h->got.offset |= 1;
   3975  1.1.1.2  christos 	      }
   3976  1.1.1.2  christos 	    else
   3977  1.1.1.2  christos 	      {
   3978  1.1.1.2  christos 		got_off = local_got_offsets[r_symndx];
   3979  1.1.1.2  christos 		local_got_offsets[r_symndx] |= 1;
   3980  1.1.1.2  christos 	      }
   3981  1.1.1.2  christos 
   3982  1.1.1.2  christos 	    BFD_ASSERT (got_off != MINUS_ONE);
   3983  1.1.1.2  christos 
   3984  1.1.1.2  christos 	    ie_off = 0;
   3985  1.1.1.2  christos 	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
   3986  1.1.1.2  christos 	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
   3987  1.1.1.2  christos 	      ie_off = 2 * GOT_ENTRY_SIZE;
   3988  1.1.1.2  christos 
   3989  1.1.1.2  christos 	    if ((got_off & 1) == 0)
   3990  1.1.1.2  christos 	      {
   3991  1.1.1.2  christos 		Elf_Internal_Rela rela;
   3992  1.1.1.2  christos 		asection *srel = htab->elf.srelgot;
   3993      1.1  christos 
   3994  1.1.1.3  christos 		int indx = 0;
   3995  1.1.1.3  christos 		bool need_reloc = false;
   3996  1.1.1.3  christos 		LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx,
   3997  1.1.1.3  christos 						need_reloc);
   3998      1.1  christos 
   3999  1.1.1.2  christos 		if (tls_type & GOT_TLS_GD)
   4000  1.1.1.2  christos 		  {
   4001  1.1.1.3  christos 		    if (need_reloc)
   4002  1.1.1.2  christos 		      {
   4003  1.1.1.3  christos 			/* Dynamic resolved Module ID.  */
   4004  1.1.1.3  christos 			rela.r_offset = sec_addr (got) + got_off;
   4005  1.1.1.3  christos 			rela.r_addend = 0;
   4006  1.1.1.3  christos 			rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DTPMODNN);
   4007  1.1.1.3  christos 			bfd_put_NN (output_bfd, 0, got->contents + got_off);
   4008  1.1.1.3  christos 			loongarch_elf_append_rela (output_bfd, srel, &rela);
   4009  1.1.1.3  christos 
   4010  1.1.1.3  christos 			if (indx == 0)
   4011  1.1.1.3  christos 			  {
   4012  1.1.1.3  christos 			    /* Local symbol, tp offset has been known.  */
   4013  1.1.1.3  christos 			    BFD_ASSERT (! unresolved_reloc);
   4014  1.1.1.3  christos 			    bfd_put_NN (output_bfd,
   4015  1.1.1.3  christos 				tlsoff (info, relocation),
   4016  1.1.1.3  christos 				(got->contents + got_off + GOT_ENTRY_SIZE));
   4017  1.1.1.3  christos 			  }
   4018  1.1.1.2  christos 			else
   4019  1.1.1.2  christos 			  {
   4020  1.1.1.3  christos 			    /* Dynamic resolved block offset.  */
   4021  1.1.1.3  christos 			    bfd_put_NN (output_bfd, 0,
   4022  1.1.1.3  christos 				got->contents + got_off + GOT_ENTRY_SIZE);
   4023  1.1.1.3  christos 			    rela.r_info = ELFNN_R_INFO (indx,
   4024  1.1.1.3  christos 						R_LARCH_TLS_DTPRELNN);
   4025  1.1.1.3  christos 			    rela.r_offset += GOT_ENTRY_SIZE;
   4026  1.1.1.2  christos 			    loongarch_elf_append_rela (output_bfd, srel, &rela);
   4027  1.1.1.2  christos 			  }
   4028  1.1.1.2  christos 		      }
   4029  1.1.1.2  christos 		    else
   4030  1.1.1.2  christos 		      {
   4031  1.1.1.3  christos 			/* In a static link or an executable link with the symbol
   4032  1.1.1.3  christos 			   binding locally.  Mark it as belonging to module 1.  */
   4033  1.1.1.3  christos 			bfd_put_NN (output_bfd, 1, got->contents + got_off);
   4034  1.1.1.3  christos 			bfd_put_NN (output_bfd, tlsoff (info, relocation),
   4035  1.1.1.3  christos 			    got->contents + got_off + GOT_ENTRY_SIZE);
   4036  1.1.1.2  christos 		      }
   4037  1.1.1.2  christos 		  }
   4038  1.1.1.2  christos 		if (tls_type & GOT_TLS_IE)
   4039  1.1.1.2  christos 		  {
   4040  1.1.1.3  christos 		    if (need_reloc)
   4041  1.1.1.2  christos 		      {
   4042  1.1.1.3  christos 			bfd_put_NN (output_bfd, 0,
   4043  1.1.1.3  christos 			    got->contents + got_off + ie_off);
   4044  1.1.1.3  christos 			rela.r_offset = sec_addr (got) + got_off + ie_off;
   4045  1.1.1.3  christos 			rela.r_addend = 0;
   4046  1.1.1.2  christos 
   4047  1.1.1.3  christos 			if (indx == 0)
   4048  1.1.1.3  christos 			  rela.r_addend = tlsoff (info, relocation);
   4049  1.1.1.3  christos 			rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_TPRELNN);
   4050  1.1.1.3  christos 			loongarch_elf_append_rela (output_bfd, srel, &rela);
   4051  1.1.1.2  christos 		      }
   4052  1.1.1.2  christos 		    else
   4053  1.1.1.2  christos 		      {
   4054  1.1.1.3  christos 			/* In a static link or an executable link with the symbol
   4055  1.1.1.3  christos 			   binding locally, compute offset directly.  */
   4056  1.1.1.3  christos 			bfd_put_NN (output_bfd, tlsoff (info, relocation),
   4057  1.1.1.3  christos 			    got->contents + got_off + ie_off);
   4058  1.1.1.2  christos 		      }
   4059  1.1.1.2  christos 		  }
   4060  1.1.1.2  christos 	      }
   4061      1.1  christos 
   4062  1.1.1.2  christos 	    relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0);
   4063  1.1.1.2  christos 	  }
   4064  1.1.1.2  christos 	  break;
   4065      1.1  christos 
   4066  1.1.1.2  christos 	/* New reloc types.  */
   4067  1.1.1.2  christos 	case R_LARCH_B16:
   4068  1.1.1.2  christos 	case R_LARCH_B21:
   4069  1.1.1.2  christos 	case R_LARCH_B26:
   4070  1.1.1.2  christos 	case R_LARCH_CALL36:
   4071  1.1.1.2  christos 	  unresolved_reloc = false;
   4072  1.1.1.3  christos 	  bool via_plt =
   4073  1.1.1.3  christos 	    plt != NULL && h != NULL && h->plt.offset != (bfd_vma) - 1;
   4074  1.1.1.3  christos 
   4075  1.1.1.2  christos 	  if (is_undefweak)
   4076      1.1  christos 	    {
   4077  1.1.1.2  christos 	      relocation = 0;
   4078  1.1.1.3  christos 
   4079  1.1.1.3  christos 	      /* A call to an undefined weak symbol is converted to 0.  */
   4080  1.1.1.3  christos 	      if (!via_plt && IS_CALL_RELOC (r_type))
   4081  1.1.1.3  christos 		{
   4082  1.1.1.3  christos 		  /* call36 fn1 => pcaddu18i $ra,0+jirl $ra,$zero,0
   4083  1.1.1.3  christos 		     tail36 $t0,fn1 => pcaddi18i $t0,0+jirl $zero,$zero,0  */
   4084  1.1.1.3  christos 		  if (R_LARCH_CALL36 == r_type)
   4085  1.1.1.3  christos 		    {
   4086  1.1.1.3  christos 		      uint32_t jirl = bfd_get (32, input_bfd,
   4087  1.1.1.3  christos 					  contents + rel->r_offset + 4);
   4088  1.1.1.3  christos 		      uint32_t rd = LARCH_GET_RD (jirl);
   4089  1.1.1.3  christos 		      jirl = LARCH_OP_JIRL | rd;
   4090  1.1.1.3  christos 
   4091  1.1.1.3  christos 		      bfd_put (32, input_bfd, jirl,
   4092  1.1.1.3  christos 			       contents + rel->r_offset + 4);
   4093  1.1.1.3  christos 		    }
   4094  1.1.1.3  christos 		  else
   4095  1.1.1.3  christos 		    {
   4096  1.1.1.3  christos 		      uint32_t b_bl = bfd_get (32, input_bfd,
   4097  1.1.1.3  christos 					       contents + rel->r_offset);
   4098  1.1.1.3  christos 		      /* b %plt(fn1) => jirl $zero,zero,0.  */
   4099  1.1.1.3  christos 		      if (LARCH_INSN_B (b_bl))
   4100  1.1.1.3  christos 			bfd_put (32, input_bfd, LARCH_OP_JIRL,
   4101  1.1.1.3  christos 				 contents + rel->r_offset);
   4102  1.1.1.3  christos 		      else
   4103  1.1.1.3  christos 		      /* bl %plt(fn1) => jirl $ra,zero,0.  */
   4104  1.1.1.3  christos 		      bfd_put (32, input_bfd, LARCH_OP_JIRL | 0x1,
   4105  1.1.1.3  christos 			       contents + rel->r_offset);
   4106  1.1.1.3  christos 		    }
   4107  1.1.1.3  christos 		  r = bfd_reloc_continue;
   4108  1.1.1.3  christos 		  break;
   4109  1.1.1.3  christos 		}
   4110      1.1  christos 	    }
   4111      1.1  christos 
   4112  1.1.1.2  christos 	  if (resolved_local)
   4113      1.1  christos 	    {
   4114  1.1.1.2  christos 	      relocation -= pc;
   4115  1.1.1.2  christos 	      relocation += rel->r_addend;
   4116      1.1  christos 	    }
   4117  1.1.1.2  christos 	  else if (resolved_dynly)
   4118      1.1  christos 	    {
   4119  1.1.1.2  christos 	      BFD_ASSERT (h
   4120  1.1.1.2  christos 			  && (h->plt.offset != MINUS_ONE
   4121  1.1.1.2  christos 			      || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
   4122  1.1.1.2  christos 			  && rel->r_addend == 0);
   4123  1.1.1.2  christos 	      if (h && h->plt.offset == MINUS_ONE
   4124  1.1.1.2  christos 		  && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
   4125  1.1.1.2  christos 		{
   4126  1.1.1.2  christos 		  relocation -= pc;
   4127  1.1.1.2  christos 		  relocation += rel->r_addend;
   4128  1.1.1.2  christos 		}
   4129  1.1.1.2  christos 	      else
   4130  1.1.1.2  christos 		relocation = sec_addr (plt) + h->plt.offset - pc;
   4131      1.1  christos 	    }
   4132      1.1  christos 
   4133  1.1.1.2  christos 	  break;
   4134  1.1.1.2  christos 
   4135  1.1.1.2  christos 	case R_LARCH_ABS_HI20:
   4136  1.1.1.2  christos 	case R_LARCH_ABS_LO12:
   4137  1.1.1.2  christos 	case R_LARCH_ABS64_LO20:
   4138  1.1.1.2  christos 	case R_LARCH_ABS64_HI12:
   4139  1.1.1.2  christos 
   4140  1.1.1.2  christos 	  if (is_undefweak)
   4141      1.1  christos 	    {
   4142  1.1.1.2  christos 	      BFD_ASSERT (resolved_dynly);
   4143  1.1.1.2  christos 	      relocation = 0;
   4144      1.1  christos 	      break;
   4145      1.1  christos 	    }
   4146  1.1.1.2  christos 	  else if (resolved_to_const || resolved_local)
   4147  1.1.1.2  christos 	    {
   4148  1.1.1.2  christos 	      relocation += rel->r_addend;
   4149  1.1.1.2  christos 	    }
   4150  1.1.1.2  christos 	  else if (resolved_dynly)
   4151  1.1.1.2  christos 	    {
   4152  1.1.1.2  christos 	      unresolved_reloc = false;
   4153  1.1.1.2  christos 	      BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE)
   4154  1.1.1.2  christos 			  && rel->r_addend == 0);
   4155  1.1.1.2  christos 	      relocation = sec_addr (plt) + h->plt.offset;
   4156  1.1.1.2  christos 	    }
   4157      1.1  christos 
   4158  1.1.1.2  christos 	  break;
   4159      1.1  christos 
   4160  1.1.1.3  christos 	case R_LARCH_PCALA64_HI12:
   4161  1.1.1.3  christos 	  pc -= 4;
   4162  1.1.1.3  christos 	  /* Fall through.  */
   4163  1.1.1.3  christos 	case R_LARCH_PCALA64_LO20:
   4164  1.1.1.3  christos 	  pc -= 8;
   4165  1.1.1.3  christos 	  /* Fall through.  */
   4166  1.1.1.2  christos 	case R_LARCH_PCREL20_S2:
   4167  1.1.1.2  christos 	case R_LARCH_PCALA_HI20:
   4168  1.1.1.2  christos 	  unresolved_reloc = false;
   4169  1.1.1.3  christos 
   4170  1.1.1.3  christos 	  /* If sym is undef weak and it's hidden or we are doing a static
   4171  1.1.1.3  christos 	     link, (sym + addend) should be resolved to runtime address
   4172  1.1.1.3  christos 	     (0 + addend).  */
   4173  1.1.1.3  christos 	  resolve_pcrel_undef_weak =
   4174  1.1.1.3  christos 	    ((info->nointerp
   4175  1.1.1.3  christos 	      || (h && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT))
   4176  1.1.1.3  christos 	     && is_undefweak);
   4177  1.1.1.3  christos 
   4178  1.1.1.3  christos 	  if (resolve_pcrel_undef_weak)
   4179  1.1.1.3  christos 	    pc = 0;
   4180  1.1.1.3  christos 
   4181  1.1.1.2  christos 	  if (h && h->plt.offset != MINUS_ONE)
   4182  1.1.1.2  christos 	    relocation = sec_addr (plt) + h->plt.offset;
   4183      1.1  christos 	  else
   4184  1.1.1.2  christos 	    relocation += rel->r_addend;
   4185      1.1  christos 
   4186  1.1.1.3  christos 	  switch (r_type)
   4187  1.1.1.3  christos 	    {
   4188  1.1.1.3  christos 	    case R_LARCH_PCREL20_S2:
   4189  1.1.1.3  christos 	      relocation -= pc;
   4190  1.1.1.3  christos 	      if (resolve_pcrel_undef_weak)
   4191  1.1.1.3  christos 		{
   4192  1.1.1.3  christos 		  bfd_signed_vma addr = (bfd_signed_vma) relocation;
   4193  1.1.1.3  christos 		  if (addr >= 2048 || addr < -2048)
   4194  1.1.1.3  christos 		    {
   4195  1.1.1.3  christos 		      const char *msg =
   4196  1.1.1.3  christos 			_("cannot resolve R_LARCH_PCREL20_S2 against "
   4197  1.1.1.3  christos 			  "undefined weak symbol with addend out of "
   4198  1.1.1.3  christos 			  "[-2048, 2048)");
   4199  1.1.1.3  christos 		      fatal =
   4200  1.1.1.3  christos 			loongarch_reloc_is_fatal (info, input_bfd,
   4201  1.1.1.3  christos 						  input_section, rel,
   4202  1.1.1.3  christos 						  howto,
   4203  1.1.1.3  christos 						  bfd_reloc_notsupported,
   4204  1.1.1.3  christos 						  is_undefweak, name, msg);
   4205  1.1.1.3  christos 		      break;
   4206  1.1.1.3  christos 		    }
   4207  1.1.1.3  christos 
   4208  1.1.1.3  christos 		  uint32_t insn = bfd_get (32, input_bfd,
   4209  1.1.1.3  christos 					   contents + rel->r_offset);
   4210  1.1.1.3  christos 		  insn = LARCH_GET_RD (insn) | LARCH_OP_ADDI_W;
   4211  1.1.1.3  christos 		  insn |= (relocation & 0xfff) << 10;
   4212  1.1.1.3  christos 		  bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
   4213  1.1.1.3  christos 		  r = bfd_reloc_continue;
   4214  1.1.1.3  christos 		}
   4215  1.1.1.3  christos 	      break;
   4216  1.1.1.3  christos 	    case R_LARCH_PCALA_HI20:
   4217  1.1.1.3  christos 	      RELOCATE_CALC_PC32_HI20 (relocation, pc);
   4218  1.1.1.3  christos 	      if (resolve_pcrel_undef_weak)
   4219  1.1.1.3  christos 		{
   4220  1.1.1.3  christos 		  uint32_t insn = bfd_get (32, input_bfd,
   4221  1.1.1.3  christos 					   contents + rel->r_offset);
   4222  1.1.1.3  christos 		  insn = LARCH_GET_RD (insn) | LARCH_OP_LU12I_W;
   4223  1.1.1.3  christos 		  bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
   4224  1.1.1.3  christos 		}
   4225  1.1.1.3  christos 	      break;
   4226  1.1.1.3  christos 	    default:
   4227  1.1.1.3  christos 	      RELOCATE_CALC_PC64_HI32 (relocation, pc);
   4228  1.1.1.3  christos 	    }
   4229  1.1.1.2  christos 	  break;
   4230      1.1  christos 
   4231  1.1.1.2  christos 	case R_LARCH_TLS_LE_HI20_R:
   4232  1.1.1.2  christos 	  relocation += rel->r_addend;
   4233  1.1.1.3  christos 	  relocation = tlsoff (info, relocation);
   4234  1.1.1.2  christos 	  RELOCATE_TLS_TP32_HI20 (relocation);
   4235  1.1.1.2  christos 	  break;
   4236      1.1  christos 
   4237  1.1.1.2  christos 	case R_LARCH_PCALA_LO12:
   4238  1.1.1.2  christos 	  /* Not support if sym_addr in 2k page edge.
   4239  1.1.1.2  christos 	     pcalau12i pc_hi20 (sym_addr)
   4240  1.1.1.2  christos 	     ld.w/d pc_lo12 (sym_addr)
   4241  1.1.1.2  christos 	     ld.w/d pc_lo12 (sym_addr + x)
   4242  1.1.1.2  christos 	     ...
   4243  1.1.1.2  christos 	     can not calc correct address
   4244  1.1.1.2  christos 	     if sym_addr < 0x800 && sym_addr + x >= 0x800.  */
   4245  1.1.1.2  christos 
   4246  1.1.1.2  christos 	  if (h && h->plt.offset != MINUS_ONE)
   4247  1.1.1.2  christos 	    relocation = sec_addr (plt) + h->plt.offset;
   4248  1.1.1.2  christos 	  else
   4249  1.1.1.2  christos 	    relocation += rel->r_addend;
   4250  1.1.1.2  christos 
   4251  1.1.1.2  christos 	  /* For 2G jump, generate pcalau12i, jirl.  */
   4252  1.1.1.2  christos 	  /* If use jirl, turns to R_LARCH_B16.  */
   4253  1.1.1.2  christos 	  uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
   4254  1.1.1.3  christos 	  if (LARCH_INSN_JIRL (insn))
   4255  1.1.1.2  christos 	    {
   4256  1.1.1.2  christos 	      relocation &= 0xfff;
   4257  1.1.1.2  christos 	      /* Signed extend.  */
   4258  1.1.1.2  christos 	      relocation = (relocation ^ 0x800) - 0x800;
   4259  1.1.1.2  christos 
   4260  1.1.1.2  christos 	      rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
   4261  1.1.1.2  christos 	      howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
   4262  1.1.1.2  christos 	    }
   4263  1.1.1.2  christos 	  break;
   4264  1.1.1.2  christos 
   4265  1.1.1.2  christos 	case R_LARCH_GOT_PC_HI20:
   4266  1.1.1.2  christos 	case R_LARCH_GOT_HI20:
   4267  1.1.1.2  christos 	  /* Calc got offset.  */
   4268  1.1.1.2  christos 	    {
   4269  1.1.1.2  christos 	      unresolved_reloc = false;
   4270  1.1.1.2  christos 	      BFD_ASSERT (rel->r_addend == 0);
   4271  1.1.1.2  christos 
   4272  1.1.1.2  christos 	      bfd_vma got_off = 0;
   4273  1.1.1.2  christos 	      if (h != NULL)
   4274      1.1  christos 		{
   4275  1.1.1.2  christos 		  /* GOT ref or ifunc.  */
   4276  1.1.1.2  christos 		  BFD_ASSERT (h->got.offset != MINUS_ONE
   4277  1.1.1.2  christos 			      || h->type == STT_GNU_IFUNC);
   4278  1.1.1.2  christos 
   4279  1.1.1.2  christos 		  got_off = h->got.offset  & (~(bfd_vma)1);
   4280  1.1.1.2  christos 		  /* Hidden symbol not has got entry,
   4281  1.1.1.2  christos 		   * only got.plt entry so it is (plt - got).  */
   4282  1.1.1.2  christos 		  if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
   4283  1.1.1.2  christos 		    {
   4284  1.1.1.2  christos 		      bfd_vma idx;
   4285  1.1.1.2  christos 		      if (htab->elf.splt != NULL)
   4286  1.1.1.2  christos 			{
   4287  1.1.1.2  christos 			  idx = (h->plt.offset - PLT_HEADER_SIZE)
   4288  1.1.1.2  christos 			    / PLT_ENTRY_SIZE;
   4289  1.1.1.2  christos 			  got_off = sec_addr (htab->elf.sgotplt)
   4290  1.1.1.2  christos 			    + GOTPLT_HEADER_SIZE
   4291  1.1.1.2  christos 			    + (idx * GOT_ENTRY_SIZE)
   4292  1.1.1.2  christos 			    - sec_addr (htab->elf.sgot);
   4293  1.1.1.2  christos 			}
   4294  1.1.1.2  christos 		      else
   4295  1.1.1.2  christos 			{
   4296  1.1.1.2  christos 			  idx = h->plt.offset / PLT_ENTRY_SIZE;
   4297  1.1.1.2  christos 			  got_off = sec_addr (htab->elf.sgotplt)
   4298  1.1.1.2  christos 			    + (idx * GOT_ENTRY_SIZE)
   4299  1.1.1.2  christos 			    - sec_addr (htab->elf.sgot);
   4300  1.1.1.2  christos 			}
   4301  1.1.1.2  christos 		    }
   4302  1.1.1.2  christos 
   4303  1.1.1.2  christos 		  if ((h->got.offset & 1) == 0)
   4304  1.1.1.2  christos 		    {
   4305  1.1.1.2  christos 		      /* We need to generate a R_LARCH_RELATIVE reloc once
   4306  1.1.1.2  christos 		       * in loongarch_elf_finish_dynamic_symbol or now,
   4307  1.1.1.2  christos 		       * call finish_dyn && nopic
   4308  1.1.1.2  christos 		       * or !call finish_dyn && pic.  */
   4309  1.1.1.2  christos 		      if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
   4310  1.1.1.2  christos 							    bfd_link_pic (info),
   4311  1.1.1.2  christos 							    h)
   4312  1.1.1.3  christos 			  && !bfd_is_abs_section(h->root.u.def.section)
   4313  1.1.1.2  christos 			  && bfd_link_pic (info)
   4314  1.1.1.3  christos 			  && LARCH_REF_LOCAL (info, h)
   4315  1.1.1.3  christos 			  && !info->enable_dt_relr)
   4316  1.1.1.2  christos 			{
   4317  1.1.1.2  christos 			  Elf_Internal_Rela rela;
   4318  1.1.1.2  christos 			  rela.r_offset = sec_addr (got) + got_off;
   4319  1.1.1.2  christos 			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
   4320  1.1.1.2  christos 			  rela.r_addend = relocation;
   4321  1.1.1.2  christos 			  loongarch_elf_append_rela (output_bfd,
   4322  1.1.1.2  christos 						     htab->elf.srelgot, &rela);
   4323  1.1.1.2  christos 			}
   4324  1.1.1.2  christos 		      h->got.offset |= 1;
   4325  1.1.1.2  christos 		      bfd_put_NN (output_bfd, relocation,
   4326  1.1.1.2  christos 				  got->contents + got_off);
   4327      1.1  christos 		    }
   4328  1.1.1.2  christos 		}
   4329  1.1.1.2  christos 	      else
   4330  1.1.1.2  christos 		{
   4331  1.1.1.2  christos 		  BFD_ASSERT (local_got_offsets
   4332  1.1.1.2  christos 			      && local_got_offsets[r_symndx] != MINUS_ONE);
   4333  1.1.1.2  christos 
   4334  1.1.1.2  christos 		  got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
   4335  1.1.1.3  christos 		  if (sym->st_shndx != SHN_ABS
   4336  1.1.1.3  christos 		      && (local_got_offsets[r_symndx] & 1) == 0)
   4337      1.1  christos 		    {
   4338  1.1.1.3  christos 		      if (bfd_link_pic (info) && !info->enable_dt_relr)
   4339      1.1  christos 			{
   4340  1.1.1.2  christos 			  Elf_Internal_Rela rela;
   4341  1.1.1.2  christos 			  rela.r_offset = sec_addr (got) + got_off;
   4342  1.1.1.2  christos 			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
   4343  1.1.1.2  christos 			  rela.r_addend = relocation;
   4344  1.1.1.2  christos 			  loongarch_elf_append_rela (output_bfd,
   4345  1.1.1.2  christos 						     htab->elf.srelgot, &rela);
   4346      1.1  christos 			}
   4347  1.1.1.2  christos 		      local_got_offsets[r_symndx] |= 1;
   4348  1.1.1.2  christos 		    }
   4349  1.1.1.2  christos 		  bfd_put_NN (output_bfd, relocation, got->contents + got_off);
   4350  1.1.1.2  christos 		}
   4351  1.1.1.2  christos 
   4352  1.1.1.2  christos 	      relocation = got_off + sec_addr (got);
   4353  1.1.1.2  christos 	    }
   4354  1.1.1.2  christos 
   4355  1.1.1.2  christos 	  if (r_type == R_LARCH_GOT_PC_HI20)
   4356  1.1.1.2  christos 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
   4357  1.1.1.2  christos 
   4358  1.1.1.2  christos 	  break;
   4359  1.1.1.2  christos 
   4360  1.1.1.2  christos 	case R_LARCH_GOT_PC_LO12:
   4361  1.1.1.2  christos 	case R_LARCH_GOT64_PC_LO20:
   4362  1.1.1.2  christos 	case R_LARCH_GOT64_PC_HI12:
   4363  1.1.1.2  christos 	case R_LARCH_GOT_LO12:
   4364  1.1.1.2  christos 	case R_LARCH_GOT64_LO20:
   4365  1.1.1.2  christos 	case R_LARCH_GOT64_HI12:
   4366  1.1.1.2  christos 	    {
   4367  1.1.1.2  christos 	      unresolved_reloc = false;
   4368  1.1.1.2  christos 	      bfd_vma got_off;
   4369  1.1.1.2  christos 	      if (h)
   4370  1.1.1.2  christos 		got_off = h->got.offset & (~(bfd_vma)1);
   4371  1.1.1.2  christos 	      else
   4372  1.1.1.2  christos 		got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
   4373  1.1.1.2  christos 
   4374  1.1.1.2  christos 	      if (h && h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
   4375  1.1.1.2  christos 		{
   4376  1.1.1.2  christos 		  bfd_vma idx;
   4377  1.1.1.2  christos 		  if (htab->elf.splt != NULL)
   4378  1.1.1.2  christos 		    idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
   4379  1.1.1.2  christos 		  else
   4380  1.1.1.2  christos 		    idx = h->plt.offset / PLT_ENTRY_SIZE;
   4381  1.1.1.2  christos 
   4382  1.1.1.2  christos 		  got_off = sec_addr (htab->elf.sgotplt)
   4383  1.1.1.2  christos 		    + GOTPLT_HEADER_SIZE
   4384  1.1.1.2  christos 		    + (idx * GOT_ENTRY_SIZE)
   4385  1.1.1.2  christos 		    - sec_addr (htab->elf.sgot);
   4386  1.1.1.2  christos 		}
   4387  1.1.1.2  christos 
   4388  1.1.1.2  christos 	      relocation = got_off + sec_addr (got);
   4389  1.1.1.2  christos 	    }
   4390  1.1.1.2  christos 
   4391  1.1.1.2  christos 	  if (r_type == R_LARCH_GOT64_PC_HI12)
   4392  1.1.1.2  christos 	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 12);
   4393  1.1.1.2  christos 	  else if (r_type == R_LARCH_GOT64_PC_LO20)
   4394  1.1.1.2  christos 	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
   4395  1.1.1.2  christos 
   4396  1.1.1.2  christos 	  break;
   4397  1.1.1.2  christos 
   4398  1.1.1.2  christos 	case R_LARCH_TLS_LE_HI20:
   4399  1.1.1.2  christos 	case R_LARCH_TLS_LE_LO12:
   4400  1.1.1.2  christos 	case R_LARCH_TLS_LE_LO12_R:
   4401  1.1.1.2  christos 	case R_LARCH_TLS_LE64_LO20:
   4402  1.1.1.2  christos 	case R_LARCH_TLS_LE64_HI12:
   4403  1.1.1.2  christos 	  BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
   4404  1.1.1.2  christos 
   4405  1.1.1.2  christos 	  relocation += rel->r_addend;
   4406  1.1.1.3  christos 	  relocation = tlsoff (info, relocation);
   4407  1.1.1.2  christos 	  break;
   4408  1.1.1.2  christos 
   4409  1.1.1.2  christos 	/* TLS IE LD/GD process separately is troublesome.
   4410  1.1.1.2  christos 	   When a symbol is both ie and LD/GD, h->got.off |= 1
   4411  1.1.1.2  christos 	   make only one type be relocated.  We must use
   4412  1.1.1.2  christos 	   h->got.offset |= 1 and h->got.offset |= 2
   4413  1.1.1.2  christos 	   diff IE and LD/GD.  And all (got_off & (~(bfd_vma)1))
   4414  1.1.1.2  christos 	   (IE LD/GD and reusable GOT reloc) must change to
   4415  1.1.1.2  christos 	   (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
   4416  1.1.1.2  christos 	   as a tag.
   4417  1.1.1.2  christos 	   Now, LD and GD is both GOT_TLS_GD type, LD seems to
   4418  1.1.1.2  christos 	   can be omitted.  */
   4419  1.1.1.2  christos 	case R_LARCH_TLS_IE_PC_HI20:
   4420  1.1.1.2  christos 	case R_LARCH_TLS_IE_HI20:
   4421  1.1.1.2  christos 	case R_LARCH_TLS_LD_PC_HI20:
   4422  1.1.1.2  christos 	case R_LARCH_TLS_LD_HI20:
   4423  1.1.1.2  christos 	case R_LARCH_TLS_GD_PC_HI20:
   4424  1.1.1.2  christos 	case R_LARCH_TLS_GD_HI20:
   4425  1.1.1.2  christos 	case R_LARCH_TLS_DESC_PC_HI20:
   4426  1.1.1.2  christos 	case R_LARCH_TLS_DESC_HI20:
   4427  1.1.1.2  christos 	case R_LARCH_TLS_LD_PCREL20_S2:
   4428  1.1.1.2  christos 	case R_LARCH_TLS_GD_PCREL20_S2:
   4429  1.1.1.2  christos 	case R_LARCH_TLS_DESC_PCREL20_S2:
   4430  1.1.1.2  christos 	  BFD_ASSERT (rel->r_addend == 0);
   4431  1.1.1.2  christos 	  unresolved_reloc = false;
   4432  1.1.1.2  christos 
   4433  1.1.1.2  christos 	  if (r_type == R_LARCH_TLS_IE_PC_HI20
   4434  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_IE_HI20)
   4435  1.1.1.2  christos 	    is_ie = true;
   4436  1.1.1.2  christos 
   4437  1.1.1.2  christos 	  if (r_type == R_LARCH_TLS_DESC_PC_HI20
   4438  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_DESC_HI20
   4439  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
   4440  1.1.1.2  christos 	    is_desc = true;
   4441  1.1.1.2  christos 
   4442  1.1.1.2  christos 	  bfd_vma got_off = 0;
   4443  1.1.1.2  christos 	  if (h != NULL)
   4444  1.1.1.2  christos 	    {
   4445  1.1.1.2  christos 	      got_off = h->got.offset;
   4446  1.1.1.2  christos 	      h->got.offset |= 1;
   4447  1.1.1.2  christos 	    }
   4448  1.1.1.2  christos 	  else
   4449  1.1.1.2  christos 	    {
   4450  1.1.1.2  christos 	      got_off = local_got_offsets[r_symndx];
   4451  1.1.1.2  christos 	      local_got_offsets[r_symndx] |= 1;
   4452  1.1.1.2  christos 	    }
   4453  1.1.1.2  christos 
   4454  1.1.1.2  christos 	  BFD_ASSERT (got_off != MINUS_ONE);
   4455  1.1.1.2  christos 
   4456  1.1.1.2  christos 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
   4457  1.1.1.2  christos 
   4458  1.1.1.2  christos 	  /* If a tls variable is accessed in multiple ways, GD uses
   4459  1.1.1.2  christos 	     the first two slots of GOT, desc follows with two slots,
   4460  1.1.1.2  christos 	     and IE uses one slot at the end.  */
   4461  1.1.1.3  christos 	  off = 0;
   4462  1.1.1.3  christos 	  if (tls_type & GOT_TLS_GD)
   4463  1.1.1.3  christos 	    off += 2 * GOT_ENTRY_SIZE;
   4464  1.1.1.3  christos 	  desc_off = off;
   4465  1.1.1.3  christos 	  if (tls_type & GOT_TLS_GDESC)
   4466  1.1.1.3  christos 	    off += 2 * GOT_ENTRY_SIZE;
   4467  1.1.1.3  christos 	  ie_off = off;
   4468  1.1.1.2  christos 
   4469  1.1.1.2  christos 	  if ((got_off & 1) == 0)
   4470  1.1.1.2  christos 	    {
   4471  1.1.1.2  christos 	      Elf_Internal_Rela rela;
   4472  1.1.1.2  christos 	      asection *relgot = htab->elf.srelgot;
   4473  1.1.1.2  christos 
   4474  1.1.1.3  christos 	      int indx = 0;
   4475  1.1.1.3  christos 	      bool need_reloc = false;
   4476  1.1.1.3  christos 	      LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx,
   4477  1.1.1.3  christos 					      need_reloc);
   4478  1.1.1.2  christos 
   4479  1.1.1.2  christos 	      if (tls_type & GOT_TLS_GD)
   4480  1.1.1.2  christos 		{
   4481  1.1.1.3  christos 		  if (need_reloc)
   4482  1.1.1.2  christos 		    {
   4483  1.1.1.3  christos 		  /* Dynamic resolved Module ID.  */
   4484  1.1.1.3  christos 		      rela.r_offset = sec_addr (got) + got_off;
   4485  1.1.1.3  christos 		      rela.r_addend = 0;
   4486  1.1.1.3  christos 		      rela.r_info = ELFNN_R_INFO (indx,R_LARCH_TLS_DTPMODNN);
   4487  1.1.1.3  christos 		      bfd_put_NN (output_bfd, 0, got->contents + got_off);
   4488  1.1.1.3  christos 		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
   4489  1.1.1.3  christos 
   4490  1.1.1.3  christos 		      if (indx == 0)
   4491  1.1.1.3  christos 			{
   4492  1.1.1.3  christos 			  /* Local symbol, tp offset has been known.  */
   4493  1.1.1.3  christos 			  BFD_ASSERT (! unresolved_reloc);
   4494  1.1.1.3  christos 			  bfd_put_NN (output_bfd,
   4495  1.1.1.3  christos 			      tlsoff (info, relocation),
   4496  1.1.1.3  christos 			      (got->contents + got_off + GOT_ENTRY_SIZE));
   4497  1.1.1.3  christos 			}
   4498      1.1  christos 		      else
   4499      1.1  christos 			{
   4500  1.1.1.3  christos 			  /* Dynamic resolved block offset.  */
   4501  1.1.1.3  christos 			  bfd_put_NN (output_bfd, 0,
   4502  1.1.1.3  christos 			      got->contents + got_off + GOT_ENTRY_SIZE);
   4503  1.1.1.3  christos 			  rela.r_info = ELFNN_R_INFO (indx,
   4504  1.1.1.3  christos 						R_LARCH_TLS_DTPRELNN);
   4505  1.1.1.3  christos 			  rela.r_offset += GOT_ENTRY_SIZE;
   4506  1.1.1.2  christos 			  loongarch_elf_append_rela (output_bfd, relgot, &rela);
   4507  1.1.1.2  christos 			}
   4508  1.1.1.2  christos 		    }
   4509  1.1.1.2  christos 		  else
   4510  1.1.1.2  christos 		    {
   4511  1.1.1.3  christos 		      /* In a static link or an executable link with the symbol
   4512  1.1.1.3  christos 			 binding locally.  Mark it as belonging to module 1.  */
   4513  1.1.1.3  christos 		      bfd_put_NN (output_bfd, 1, got->contents + got_off);
   4514  1.1.1.3  christos 		      bfd_put_NN (output_bfd, tlsoff (info, relocation),
   4515  1.1.1.3  christos 			  got->contents + got_off + GOT_ENTRY_SIZE);
   4516  1.1.1.2  christos 		    }
   4517  1.1.1.2  christos 		}
   4518  1.1.1.2  christos 	      if (tls_type & GOT_TLS_GDESC)
   4519  1.1.1.2  christos 		{
   4520  1.1.1.2  christos 		  /* Unless it is a static link, DESC always emits a
   4521  1.1.1.2  christos 		     dynamic relocation.  */
   4522  1.1.1.3  christos 		  indx = h && h->dynindx != -1 ? h->dynindx : 0;
   4523  1.1.1.2  christos 		  rela.r_offset = sec_addr (got) + got_off + desc_off;
   4524  1.1.1.2  christos 		  rela.r_addend = 0;
   4525  1.1.1.2  christos 		  if (indx == 0)
   4526  1.1.1.3  christos 		    rela.r_addend = tlsoff (info, relocation);
   4527  1.1.1.2  christos 
   4528  1.1.1.2  christos 		  rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN);
   4529  1.1.1.2  christos 		  loongarch_elf_append_rela (output_bfd, relgot, &rela);
   4530  1.1.1.2  christos 		  bfd_put_NN (output_bfd, 0,
   4531  1.1.1.2  christos 			      got->contents + got_off + desc_off);
   4532  1.1.1.2  christos 		}
   4533  1.1.1.2  christos 	      if (tls_type & GOT_TLS_IE)
   4534  1.1.1.2  christos 		{
   4535  1.1.1.3  christos 		  if (need_reloc)
   4536  1.1.1.2  christos 		    {
   4537  1.1.1.3  christos 		      bfd_put_NN (output_bfd, 0,
   4538  1.1.1.3  christos 			  got->contents + got_off + ie_off);
   4539  1.1.1.3  christos 		      rela.r_offset = sec_addr (got) + got_off + ie_off;
   4540  1.1.1.3  christos 		      rela.r_addend = 0;
   4541  1.1.1.2  christos 
   4542  1.1.1.3  christos 		      if (indx == 0)
   4543  1.1.1.3  christos 			rela.r_addend = tlsoff (info, relocation);
   4544  1.1.1.3  christos 		      rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_TPRELNN);
   4545  1.1.1.3  christos 		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
   4546  1.1.1.2  christos 		    }
   4547  1.1.1.2  christos 		  else
   4548  1.1.1.2  christos 		    {
   4549  1.1.1.3  christos 		      /* In a static link or an executable link with the symbol
   4550  1.1.1.3  christos 			 bindinglocally, compute offset directly.  */
   4551  1.1.1.3  christos 		      bfd_put_NN (output_bfd, tlsoff (info, relocation),
   4552  1.1.1.3  christos 			  got->contents + got_off + ie_off);
   4553      1.1  christos 		    }
   4554      1.1  christos 		}
   4555      1.1  christos 	    }
   4556  1.1.1.2  christos 	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got);
   4557  1.1.1.2  christos 	  if (is_desc)
   4558  1.1.1.2  christos 	    relocation += desc_off;
   4559  1.1.1.2  christos 	  else if (is_ie)
   4560  1.1.1.2  christos 	    relocation += ie_off;
   4561  1.1.1.2  christos 
   4562  1.1.1.2  christos 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
   4563  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_GD_PC_HI20
   4564  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_IE_PC_HI20
   4565  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
   4566  1.1.1.2  christos 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
   4567  1.1.1.2  christos 	  else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
   4568  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_GD_PCREL20_S2
   4569  1.1.1.2  christos 	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
   4570  1.1.1.2  christos 	    relocation -= pc;
   4571  1.1.1.2  christos 	  /* else {} ABS relocations.  */
   4572  1.1.1.2  christos 	  break;
   4573  1.1.1.2  christos 
   4574  1.1.1.2  christos 	case R_LARCH_TLS_DESC_PC_LO12:
   4575  1.1.1.2  christos 	case R_LARCH_TLS_DESC64_PC_LO20:
   4576  1.1.1.2  christos 	case R_LARCH_TLS_DESC64_PC_HI12:
   4577  1.1.1.2  christos 	case R_LARCH_TLS_DESC_LO12:
   4578  1.1.1.2  christos 	case R_LARCH_TLS_DESC64_LO20:
   4579  1.1.1.2  christos 	case R_LARCH_TLS_DESC64_HI12:
   4580  1.1.1.2  christos 	  {
   4581  1.1.1.2  christos 	    unresolved_reloc = false;
   4582  1.1.1.2  christos 
   4583  1.1.1.2  christos 	    if (h)
   4584  1.1.1.2  christos 	      relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
   4585  1.1.1.2  christos 	    else
   4586  1.1.1.2  christos 	      relocation = sec_addr (got)
   4587  1.1.1.2  christos 			   + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
   4588  1.1.1.2  christos 
   4589  1.1.1.2  christos 	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
   4590  1.1.1.2  christos 	    /* Use both TLS_GD and TLS_DESC.  */
   4591  1.1.1.3  christos 	    if (GOT_TLS_GD_BOTH_P (tls_type))
   4592  1.1.1.2  christos 	      relocation += 2 * GOT_ENTRY_SIZE;
   4593  1.1.1.2  christos 
   4594  1.1.1.2  christos 	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20)
   4595  1.1.1.2  christos 	      RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
   4596  1.1.1.2  christos 	    else if (r_type == R_LARCH_TLS_DESC64_PC_HI12)
   4597  1.1.1.2  christos 	      RELOCATE_CALC_PC64_HI32 (relocation, pc - 12);
   4598  1.1.1.2  christos 
   4599  1.1.1.2  christos 	    break;
   4600  1.1.1.2  christos 	  }
   4601  1.1.1.2  christos 
   4602  1.1.1.2  christos 	case R_LARCH_TLS_DESC_LD:
   4603  1.1.1.2  christos 	case R_LARCH_TLS_DESC_CALL:
   4604  1.1.1.2  christos 	  unresolved_reloc = false;
   4605  1.1.1.2  christos 	  break;
   4606      1.1  christos 
   4607  1.1.1.2  christos 	case R_LARCH_TLS_IE_PC_LO12:
   4608  1.1.1.2  christos 	case R_LARCH_TLS_IE64_PC_LO20:
   4609  1.1.1.2  christos 	case R_LARCH_TLS_IE64_PC_HI12:
   4610  1.1.1.2  christos 	case R_LARCH_TLS_IE_LO12:
   4611  1.1.1.2  christos 	case R_LARCH_TLS_IE64_LO20:
   4612  1.1.1.2  christos 	case R_LARCH_TLS_IE64_HI12:
   4613  1.1.1.2  christos 	  unresolved_reloc = false;
   4614  1.1.1.2  christos 
   4615  1.1.1.2  christos 	  if (h)
   4616  1.1.1.2  christos 	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
   4617  1.1.1.2  christos 	  else
   4618  1.1.1.2  christos 	    relocation = sec_addr (got)
   4619  1.1.1.2  christos 	      + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
   4620  1.1.1.2  christos 
   4621  1.1.1.2  christos 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
   4622  1.1.1.2  christos 	  /* Use TLS_GD TLS_DESC and TLS_IE.  */
   4623  1.1.1.2  christos 	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
   4624  1.1.1.2  christos 	    relocation += 4 * GOT_ENTRY_SIZE;
   4625  1.1.1.2  christos 	  /* Use GOT_TLS_GD_ANY_P (tls_type) and TLS_IE.  */
   4626  1.1.1.2  christos 	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
   4627  1.1.1.2  christos 	    relocation += 2 * GOT_ENTRY_SIZE;
   4628  1.1.1.2  christos 
   4629  1.1.1.2  christos 	  if (r_type == R_LARCH_TLS_IE64_PC_LO20)
   4630  1.1.1.2  christos 	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
   4631  1.1.1.2  christos 	  else if (r_type == R_LARCH_TLS_IE64_PC_HI12)
   4632  1.1.1.2  christos 	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 12);
   4633  1.1.1.2  christos 
   4634  1.1.1.2  christos 	  break;
   4635  1.1.1.2  christos 
   4636  1.1.1.2  christos 	case R_LARCH_RELAX:
   4637  1.1.1.2  christos 	case R_LARCH_ALIGN:
   4638  1.1.1.2  christos 	  r = bfd_reloc_continue;
   4639  1.1.1.2  christos 	  unresolved_reloc = false;
   4640      1.1  christos 	  break;
   4641      1.1  christos 
   4642      1.1  christos 	default:
   4643      1.1  christos 	  break;
   4644      1.1  christos 	}
   4645      1.1  christos 
   4646      1.1  christos       if (fatal)
   4647      1.1  christos 	break;
   4648      1.1  christos 
   4649      1.1  christos       do
   4650      1.1  christos 	{
   4651      1.1  christos 	  /* 'unresolved_reloc' means we haven't done it yet.
   4652      1.1  christos 	     We need help of dynamic linker to fix this memory location up.  */
   4653      1.1  christos 	  if (!unresolved_reloc)
   4654      1.1  christos 	    break;
   4655      1.1  christos 
   4656      1.1  christos 	  if (_bfd_elf_section_offset (output_bfd, info, input_section,
   4657      1.1  christos 				       rel->r_offset) == MINUS_ONE)
   4658      1.1  christos 	    /* WHY? May because it's invalid so skip checking.
   4659  1.1.1.2  christos 	       But why dynamic reloc a invalid section?  */
   4660      1.1  christos 	    break;
   4661      1.1  christos 
   4662      1.1  christos 	  if (input_section->output_section->flags & SEC_DEBUGGING)
   4663      1.1  christos 	    {
   4664      1.1  christos 	      fatal = (loongarch_reloc_is_fatal
   4665      1.1  christos 		       (info, input_bfd, input_section, rel, howto,
   4666      1.1  christos 			bfd_reloc_dangerous, is_undefweak, name,
   4667      1.1  christos 			"Seems dynamic linker not process "
   4668      1.1  christos 			"sections 'SEC_DEBUGGING'."));
   4669      1.1  christos 	    }
   4670      1.1  christos 	  if (!is_dyn)
   4671      1.1  christos 	    break;
   4672      1.1  christos 
   4673      1.1  christos 	  if ((info->flags & DF_TEXTREL) == 0)
   4674      1.1  christos 	    if (input_section->output_section->flags & SEC_READONLY)
   4675      1.1  christos 	      info->flags |= DF_TEXTREL;
   4676      1.1  christos 	}
   4677      1.1  christos       while (0);
   4678      1.1  christos 
   4679      1.1  christos       if (fatal)
   4680      1.1  christos 	break;
   4681      1.1  christos 
   4682      1.1  christos       loongarch_record_one_reloc (input_bfd, input_section, r_type,
   4683      1.1  christos 				  rel->r_offset, sym, h, rel->r_addend);
   4684      1.1  christos 
   4685      1.1  christos       if (r != bfd_reloc_continue)
   4686      1.1  christos 	r = perform_relocation (rel, input_section, howto, relocation,
   4687      1.1  christos 				input_bfd, contents);
   4688      1.1  christos 
   4689      1.1  christos       switch (r)
   4690      1.1  christos 	{
   4691      1.1  christos 	case bfd_reloc_dangerous:
   4692      1.1  christos 	case bfd_reloc_continue:
   4693      1.1  christos 	case bfd_reloc_ok:
   4694      1.1  christos 	  continue;
   4695      1.1  christos 
   4696      1.1  christos 	case bfd_reloc_overflow:
   4697      1.1  christos 	  /* Overflow value can't be filled in.  */
   4698      1.1  christos 	  loongarch_dump_reloc_record (info->callbacks->info);
   4699      1.1  christos 	  info->callbacks->reloc_overflow
   4700      1.1  christos 	    (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
   4701      1.1  christos 	     input_bfd, input_section, rel->r_offset);
   4702  1.1.1.3  christos 	  if (r_type == R_LARCH_PCREL20_S2
   4703  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_LD_PCREL20_S2
   4704  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_GD_PCREL20_S2
   4705  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
   4706  1.1.1.3  christos 	    _bfd_error_handler (_("recompile with 'gcc -mno-relax' or"
   4707  1.1.1.3  christos 				  " 'as -mno-relax' or 'ld --no-relax'"));
   4708      1.1  christos 	  break;
   4709      1.1  christos 
   4710      1.1  christos 	case bfd_reloc_outofrange:
   4711      1.1  christos 	  /* Stack state incorrect.  */
   4712      1.1  christos 	  loongarch_dump_reloc_record (info->callbacks->info);
   4713      1.1  christos 	  info->callbacks->info
   4714      1.1  christos 	    ("%X%H: Internal stack state is incorrect.\n"
   4715      1.1  christos 	     "Want to push to full stack or pop from empty stack?\n",
   4716      1.1  christos 	     input_bfd, input_section, rel->r_offset);
   4717      1.1  christos 	  break;
   4718      1.1  christos 
   4719      1.1  christos 	case bfd_reloc_notsupported:
   4720      1.1  christos 	  info->callbacks->info ("%X%H: Unknown relocation type.\n", input_bfd,
   4721      1.1  christos 				 input_section, rel->r_offset);
   4722      1.1  christos 	  break;
   4723      1.1  christos 
   4724      1.1  christos 	default:
   4725      1.1  christos 	  info->callbacks->info ("%X%H: Internal: unknown error.\n", input_bfd,
   4726      1.1  christos 				 input_section, rel->r_offset);
   4727      1.1  christos 	  break;
   4728      1.1  christos 	}
   4729      1.1  christos 
   4730      1.1  christos       fatal = true;
   4731      1.1  christos     }
   4732      1.1  christos 
   4733      1.1  christos   return !fatal;
   4734      1.1  christos }
   4735      1.1  christos 
   4736  1.1.1.3  christos /* A pending delete op during a linker relaxation trip, to be stored in a
   4737  1.1.1.3  christos    splay tree.
   4738  1.1.1.3  christos    The key is the starting offset of this op's deletion range, interpreted
   4739  1.1.1.3  christos    as if no delete op were executed for this trip.  */
   4740  1.1.1.3  christos struct pending_delete_op
   4741  1.1.1.3  christos {
   4742  1.1.1.3  christos   /* Number of bytes to delete at the address.  */
   4743  1.1.1.3  christos   bfd_size_type size;
   4744  1.1.1.3  christos 
   4745  1.1.1.3  christos   /* The total offset adjustment at the address as if all preceding delete
   4746  1.1.1.3  christos      ops had been executed.  Used for calculating expected addresses after
   4747  1.1.1.3  christos      relaxation without actually adjusting anything.  */
   4748  1.1.1.3  christos   bfd_size_type cumulative_offset;
   4749  1.1.1.3  christos };
   4750  1.1.1.3  christos 
   4751  1.1.1.3  christos static int
   4752  1.1.1.3  christos pending_delete_op_compare (splay_tree_key a, splay_tree_key b)
   4753  1.1.1.3  christos {
   4754  1.1.1.3  christos   bfd_vma off_a = (bfd_vma)a;
   4755  1.1.1.3  christos   bfd_vma off_b = (bfd_vma)b;
   4756  1.1.1.3  christos 
   4757  1.1.1.3  christos   if (off_a < off_b)
   4758  1.1.1.3  christos     return -1;
   4759  1.1.1.3  christos   else if (off_a > off_b)
   4760  1.1.1.3  christos     return 1;
   4761  1.1.1.3  christos   else
   4762  1.1.1.3  christos     return 0;
   4763  1.1.1.3  christos }
   4764  1.1.1.3  christos 
   4765  1.1.1.3  christos static void *
   4766  1.1.1.3  christos _allocate_on_bfd (int wanted, void *data)
   4767  1.1.1.3  christos {
   4768  1.1.1.3  christos   bfd *abfd = (bfd *)data;
   4769  1.1.1.3  christos   return bfd_alloc (abfd, wanted);
   4770  1.1.1.3  christos }
   4771  1.1.1.3  christos 
   4772  1.1.1.3  christos static void
   4773  1.1.1.3  christos _deallocate_on_bfd (void *p ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
   4774  1.1.1.3  christos {
   4775  1.1.1.3  christos   /* Nothing to do; the data will get released along with the associated BFD
   4776  1.1.1.3  christos      or an early bfd_release call.  */
   4777  1.1.1.3  christos }
   4778  1.1.1.3  christos 
   4779  1.1.1.3  christos static splay_tree
   4780  1.1.1.3  christos pending_delete_ops_new (bfd *abfd)
   4781  1.1.1.3  christos {
   4782  1.1.1.3  christos   /* The node values are allocated with bfd_zalloc, so they are automatically
   4783  1.1.1.3  christos      taken care of at BFD release time.  */
   4784  1.1.1.3  christos   return splay_tree_new_with_allocator (pending_delete_op_compare, NULL, NULL,
   4785  1.1.1.3  christos       _allocate_on_bfd, _deallocate_on_bfd, abfd);
   4786  1.1.1.3  christos }
   4787  1.1.1.3  christos 
   4788  1.1.1.3  christos static bfd_vma
   4789  1.1.1.3  christos loongarch_calc_relaxed_addr (struct bfd_link_info *info, bfd_vma offset)
   4790  1.1.1.3  christos {
   4791  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   4792  1.1.1.3  christos   splay_tree pdops = htab->pending_delete_ops;
   4793  1.1.1.3  christos   struct pending_delete_op *op;
   4794  1.1.1.3  christos   splay_tree_node node;
   4795  1.1.1.3  christos 
   4796  1.1.1.3  christos   if (!pdops)
   4797  1.1.1.3  christos     /* Currently this means we are past the stages where byte deletion could
   4798  1.1.1.3  christos        possibly happen.  */
   4799  1.1.1.3  christos     return offset;
   4800  1.1.1.3  christos 
   4801  1.1.1.3  christos   /* Find the op that starts just before the given address.  */
   4802  1.1.1.3  christos   node = splay_tree_predecessor (pdops, (splay_tree_key)offset);
   4803  1.1.1.3  christos   if (node == NULL)
   4804  1.1.1.3  christos     /* Nothing has been deleted yet.  */
   4805  1.1.1.3  christos     return offset;
   4806  1.1.1.3  christos   BFD_ASSERT (((bfd_vma)node->key) < offset);
   4807  1.1.1.3  christos   op = (struct pending_delete_op *)node->value;
   4808  1.1.1.3  christos 
   4809  1.1.1.3  christos   /* If offset is inside this op's range, it is actually one of the deleted
   4810  1.1.1.3  christos      bytes, so the adjusted node->key should be returned in this case.  */
   4811  1.1.1.3  christos   bfd_vma op_end_off = (bfd_vma)node->key + op->size;
   4812  1.1.1.3  christos   if (offset < op_end_off)
   4813  1.1.1.3  christos     {
   4814  1.1.1.3  christos       offset = (bfd_vma)node->key;
   4815  1.1.1.3  christos       node = splay_tree_predecessor (pdops, node->key);
   4816  1.1.1.3  christos       op = node ? (struct pending_delete_op *)node->value : NULL;
   4817  1.1.1.3  christos     }
   4818  1.1.1.3  christos 
   4819  1.1.1.3  christos   return offset - (op ? op->cumulative_offset : 0);
   4820  1.1.1.3  christos }
   4821  1.1.1.3  christos 
   4822  1.1.1.3  christos static void
   4823  1.1.1.2  christos loongarch_relax_delete_bytes (bfd *abfd,
   4824  1.1.1.3  christos 			      bfd_vma addr,
   4825  1.1.1.3  christos 			      size_t count,
   4826  1.1.1.3  christos 			      struct bfd_link_info *link_info)
   4827  1.1.1.2  christos {
   4828  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab
   4829  1.1.1.3  christos       = loongarch_elf_hash_table (link_info);
   4830  1.1.1.3  christos   splay_tree pdops = htab->pending_delete_ops;
   4831  1.1.1.3  christos   splay_tree_node node;
   4832  1.1.1.3  christos   struct pending_delete_op *op = NULL, *new_op = NULL;
   4833  1.1.1.3  christos   bool need_new_node = true;
   4834  1.1.1.2  christos 
   4835  1.1.1.3  christos   if (count == 0)
   4836  1.1.1.3  christos     return;
   4837  1.1.1.2  christos 
   4838  1.1.1.3  christos   BFD_ASSERT (pdops != NULL);
   4839  1.1.1.2  christos 
   4840  1.1.1.3  christos   node = splay_tree_predecessor (pdops, addr);
   4841  1.1.1.3  christos   if (node)
   4842  1.1.1.2  christos     {
   4843  1.1.1.3  christos       op = (struct pending_delete_op *)node->value;
   4844  1.1.1.3  christos       if ((bfd_vma)node->key + op->size >= addr)
   4845  1.1.1.2  christos 	{
   4846  1.1.1.3  christos 	  /* The previous op already covers this offset, coalesce the new op
   4847  1.1.1.3  christos 	     into it.  */
   4848  1.1.1.3  christos 	  op->size += count;
   4849  1.1.1.3  christos 	  op->cumulative_offset += count;
   4850  1.1.1.3  christos 	  need_new_node = false;
   4851  1.1.1.2  christos 	}
   4852  1.1.1.2  christos     }
   4853  1.1.1.2  christos 
   4854  1.1.1.3  christos   if (need_new_node)
   4855  1.1.1.2  christos     {
   4856  1.1.1.3  christos       new_op = bfd_zalloc (abfd, sizeof (struct pending_delete_op));
   4857  1.1.1.3  christos       new_op->size = count;
   4858  1.1.1.3  christos       new_op->cumulative_offset = (op ? op->cumulative_offset : 0) + count;
   4859  1.1.1.3  christos       node = splay_tree_insert (pdops, (splay_tree_key)addr,
   4860  1.1.1.3  christos 				(splay_tree_value)new_op);
   4861  1.1.1.3  christos     }
   4862  1.1.1.3  christos 
   4863  1.1.1.3  christos   /* Adjust all cumulative offsets after this op.  At this point either:
   4864  1.1.1.3  christos      - a new node is created, in which case `node` has been updated with the
   4865  1.1.1.3  christos        new value, or
   4866  1.1.1.3  christos      - an existing node is to be reused, in which case `node` is untouched by
   4867  1.1.1.3  christos        the new node logic above and appropriate to use,
   4868  1.1.1.3  christos      so we can just re-use `node` here.  */
   4869  1.1.1.3  christos   for (node = splay_tree_successor (pdops, node->key); node != NULL;
   4870  1.1.1.3  christos        node = splay_tree_successor (pdops, node->key))
   4871  1.1.1.3  christos     {
   4872  1.1.1.3  christos       op = (struct pending_delete_op *)node->value;
   4873  1.1.1.3  christos       op->cumulative_offset += count;
   4874  1.1.1.3  christos     }
   4875  1.1.1.3  christos }
   4876  1.1.1.3  christos 
   4877  1.1.1.3  christos static void
   4878  1.1.1.3  christos loongarch_relax_delete_or_nop (bfd *abfd,
   4879  1.1.1.3  christos 			       asection *sec,
   4880  1.1.1.3  christos 			       bfd_vma addr,
   4881  1.1.1.3  christos 			       size_t count,
   4882  1.1.1.3  christos 			       struct bfd_link_info *link_info)
   4883  1.1.1.3  christos {
   4884  1.1.1.3  christos   struct bfd_elf_section_data *data = elf_section_data (sec);
   4885  1.1.1.3  christos   bfd_byte *contents = data->this_hdr.contents;
   4886  1.1.1.3  christos 
   4887  1.1.1.3  christos   BFD_ASSERT (count % 4 == 0);
   4888  1.1.1.3  christos 
   4889  1.1.1.3  christos   if (!loongarch_sec_closed_for_deletion (sec))
   4890  1.1.1.3  christos     {
   4891  1.1.1.3  christos       /* Deletions are still possible within the section.  */
   4892  1.1.1.3  christos       loongarch_relax_delete_bytes (abfd, addr, count, link_info);
   4893  1.1.1.3  christos       return;
   4894  1.1.1.3  christos     }
   4895  1.1.1.3  christos 
   4896  1.1.1.3  christos   /* We can no longer delete bytes in the section after enforcing alignment.
   4897  1.1.1.3  christos      But as the resulting shrinkage may open up a few more relaxation chances,
   4898  1.1.1.3  christos      allowing unnecessary instructions to be replaced with NOPs instead of
   4899  1.1.1.3  christos      being removed altogether may still benefit performance to a lesser
   4900  1.1.1.3  christos      extent.  */
   4901  1.1.1.3  christos   for (; count; addr += 4, count -= 4)
   4902  1.1.1.3  christos     bfd_put (32, abfd, LARCH_NOP, contents + addr);
   4903  1.1.1.3  christos }
   4904  1.1.1.3  christos 
   4905  1.1.1.3  christos static void
   4906  1.1.1.3  christos loongarch_relax_perform_deletes (bfd *abfd, asection *sec,
   4907  1.1.1.3  christos 				 struct bfd_link_info *link_info)
   4908  1.1.1.3  christos {
   4909  1.1.1.3  christos   unsigned int i, symcount;
   4910  1.1.1.3  christos   bfd_vma toaddr = sec->size;
   4911  1.1.1.3  christos   struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
   4912  1.1.1.3  christos   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   4913  1.1.1.3  christos   unsigned int sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
   4914  1.1.1.3  christos   struct bfd_elf_section_data *data = elf_section_data (sec);
   4915  1.1.1.3  christos   bfd_byte *contents = data->this_hdr.contents, *contents_end = NULL;
   4916  1.1.1.3  christos   struct relr_entry *relr = loongarch_elf_section_data (sec)->relr;
   4917  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab =
   4918  1.1.1.3  christos     loongarch_elf_hash_table (link_info);
   4919  1.1.1.3  christos   struct relr_entry *relr_end = NULL;
   4920  1.1.1.3  christos   splay_tree pdops = htab->pending_delete_ops;
   4921  1.1.1.3  christos   splay_tree_node node1 = NULL, node2 = NULL;
   4922  1.1.1.3  christos 
   4923  1.1.1.3  christos   if (htab->relr_count)
   4924  1.1.1.3  christos     relr_end = htab->relr + htab->relr_count;
   4925  1.1.1.3  christos 
   4926  1.1.1.3  christos   BFD_ASSERT (pdops != NULL);
   4927  1.1.1.3  christos   node1 = splay_tree_min (pdops);
   4928  1.1.1.3  christos 
   4929  1.1.1.3  christos   if (node1 == NULL)
   4930  1.1.1.3  christos     /* No pending delete ops, nothing to do.  */
   4931  1.1.1.3  christos     return;
   4932  1.1.1.3  christos 
   4933  1.1.1.3  christos   /* Actually delete the bytes.  For each delete op the pointer arithmetics
   4934  1.1.1.3  christos      look like this:
   4935  1.1.1.3  christos 
   4936  1.1.1.3  christos 	     node1->key -\			/- node2->key
   4937  1.1.1.3  christos 			 |<- op1->size ->|      |
   4938  1.1.1.3  christos 			 v		 v      v
   4939  1.1.1.3  christos 	...-DDDDDD-------xxxxxxxxxxxxxxxxxSSSSSSxxxxxxxxxx----...
   4940  1.1.1.3  christos 	    ^     ^			  ^
   4941  1.1.1.3  christos 	    contents_end		  node1->key + op1->size
   4942  1.1.1.3  christos 		  |
   4943  1.1.1.3  christos 		  contents_end after this memmove
   4944  1.1.1.3  christos 
   4945  1.1.1.3  christos      where the "S" and "D" bytes are the memmove's source and destination
   4946  1.1.1.3  christos      respectively.  In case node1 is the first op, contents_end is initialized
   4947  1.1.1.3  christos      to the op's start; in case node2 == NULL, the chunk's end is the section's
   4948  1.1.1.3  christos      end.  The contents_end pointer will be bumped to the new end of content
   4949  1.1.1.3  christos      after each memmove.  As no byte is added during the process, it is
   4950  1.1.1.3  christos      guaranteed to trail behind the delete ops, and all bytes overwritten are
   4951  1.1.1.3  christos      either already copied by an earlier memmove or meant to be discarded.
   4952  1.1.1.3  christos 
   4953  1.1.1.3  christos      For memmove, we need to translate offsets to pointers by adding them to
   4954  1.1.1.3  christos      `contents`.  */
   4955  1.1.1.3  christos   for (; node1; node1 = node2)
   4956  1.1.1.3  christos     {
   4957  1.1.1.3  christos       struct pending_delete_op *op1 = (struct pending_delete_op *)node1->value;
   4958  1.1.1.3  christos       bfd_vma op1_start_off = (bfd_vma)node1->key;
   4959  1.1.1.3  christos       bfd_vma op1_end_off = op1_start_off + op1->size;
   4960  1.1.1.3  christos       node2 = splay_tree_successor (pdops, node1->key);
   4961  1.1.1.3  christos       bfd_vma op2_start_off = node2 ? (bfd_vma)node2->key : toaddr;
   4962  1.1.1.3  christos       bfd_size_type count = op2_start_off - op1_end_off;
   4963  1.1.1.3  christos 
   4964  1.1.1.3  christos       if (count)
   4965  1.1.1.3  christos 	{
   4966  1.1.1.3  christos 	  if (contents_end == NULL)
   4967  1.1.1.3  christos 	    /* Start from the end of the first unmodified content chunk.  */
   4968  1.1.1.3  christos 	    contents_end = contents + op1_start_off;
   4969  1.1.1.3  christos 
   4970  1.1.1.3  christos 	  memmove (contents_end, contents + op1_end_off, count);
   4971  1.1.1.3  christos 	  contents_end += count;
   4972  1.1.1.3  christos 	}
   4973  1.1.1.3  christos 
   4974  1.1.1.3  christos       /* Adjust the section size once, when we have reached the end.  */
   4975  1.1.1.3  christos       if (node2 == NULL)
   4976  1.1.1.3  christos 	sec->size -= op1->cumulative_offset;
   4977  1.1.1.3  christos     }
   4978  1.1.1.3  christos 
   4979  1.1.1.3  christos   /* Adjust the location of all of the relocs.  Note that we need not
   4980  1.1.1.3  christos      adjust the addends, since all PC-relative references must be against
   4981  1.1.1.3  christos      symbols, which we will adjust below.  */
   4982  1.1.1.3  christos   for (i = 0; i < sec->reloc_count; i++)
   4983  1.1.1.3  christos     if (data->relocs[i].r_offset < toaddr)
   4984  1.1.1.3  christos       data->relocs[i].r_offset = loongarch_calc_relaxed_addr (
   4985  1.1.1.3  christos 	  link_info, data->relocs[i].r_offset);
   4986  1.1.1.3  christos 
   4987  1.1.1.3  christos   /* Likewise for relative relocs to be packed into .relr.  */
   4988  1.1.1.3  christos   for (; relr && relr < relr_end && relr->sec == sec; relr++)
   4989  1.1.1.3  christos     if (relr->off < toaddr)
   4990  1.1.1.3  christos       relr->off = loongarch_calc_relaxed_addr (link_info, relr->off);
   4991  1.1.1.3  christos 
   4992  1.1.1.3  christos   /* Adjust the local symbols defined in this section.  */
   4993  1.1.1.3  christos   for (i = 0; i < symtab_hdr->sh_info; i++)
   4994  1.1.1.3  christos     {
   4995  1.1.1.3  christos       Elf_Internal_Sym *sym = (Elf_Internal_Sym *) symtab_hdr->contents + i;
   4996  1.1.1.3  christos       if (sym->st_shndx == sec_shndx)
   4997  1.1.1.3  christos 	{
   4998  1.1.1.3  christos 	  bfd_vma orig_value = sym->st_value;
   4999  1.1.1.3  christos 	  if (orig_value <= toaddr)
   5000  1.1.1.3  christos 	    sym->st_value
   5001  1.1.1.3  christos 		= loongarch_calc_relaxed_addr (link_info, orig_value);
   5002  1.1.1.3  christos 
   5003  1.1.1.3  christos 	  /* If the symbol *spans* some deleted bytes, that is its *end* is in
   5004  1.1.1.3  christos 	     the moved bytes but its *start* isn't, then we must adjust its
   5005  1.1.1.3  christos 	     size.
   5006  1.1.1.3  christos 
   5007  1.1.1.3  christos 	     This test needs to use the original value of st_value, otherwise
   5008  1.1.1.3  christos 	     we might accidentally decrease size when deleting bytes right
   5009  1.1.1.3  christos 	     before the symbol.  */
   5010  1.1.1.3  christos 	  bfd_vma sym_end = orig_value + sym->st_size;
   5011  1.1.1.3  christos 	  if (sym_end <= toaddr)
   5012  1.1.1.3  christos 	    {
   5013  1.1.1.3  christos 	      splay_tree_node node = splay_tree_predecessor (
   5014  1.1.1.3  christos 		  pdops, (splay_tree_key)orig_value);
   5015  1.1.1.3  christos 	      for (; node; node = splay_tree_successor (pdops, node->key))
   5016  1.1.1.3  christos 		{
   5017  1.1.1.3  christos 		  bfd_vma addr = (bfd_vma)node->key;
   5018  1.1.1.3  christos 		  struct pending_delete_op *op
   5019  1.1.1.3  christos 		      = (struct pending_delete_op *)node->value;
   5020  1.1.1.3  christos 
   5021  1.1.1.3  christos 		  if (addr >= sym_end)
   5022  1.1.1.3  christos 		    break;
   5023  1.1.1.3  christos 		  if (orig_value <= addr && sym_end > addr)
   5024  1.1.1.3  christos 		    sym->st_size -= op->size;
   5025  1.1.1.3  christos 		}
   5026  1.1.1.3  christos 	    }
   5027  1.1.1.3  christos 	}
   5028  1.1.1.3  christos     }
   5029  1.1.1.3  christos 
   5030  1.1.1.3  christos   /* Now adjust the global symbols defined in this section.  */
   5031  1.1.1.3  christos   symcount = ((symtab_hdr->sh_size / sizeof (ElfNN_External_Sym))
   5032  1.1.1.3  christos 	      - symtab_hdr->sh_info);
   5033  1.1.1.3  christos 
   5034  1.1.1.3  christos   for (i = 0; i < symcount; i++)
   5035  1.1.1.3  christos     {
   5036  1.1.1.3  christos       struct elf_link_hash_entry *sym_hash = sym_hashes[i];
   5037  1.1.1.2  christos 
   5038  1.1.1.2  christos       /* The '--wrap SYMBOL' option is causing a pain when the object file,
   5039  1.1.1.2  christos 	 containing the definition of __wrap_SYMBOL, includes a direct
   5040  1.1.1.2  christos 	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
   5041  1.1.1.2  christos 	 the same symbol (which is __wrap_SYMBOL), but still exist as two
   5042  1.1.1.2  christos 	 different symbols in 'sym_hashes', we don't want to adjust
   5043  1.1.1.2  christos 	 the global symbol __wrap_SYMBOL twice.
   5044  1.1.1.2  christos 
   5045  1.1.1.2  christos 	 The same problem occurs with symbols that are versioned_hidden, as
   5046  1.1.1.2  christos 	 foo becomes an alias for foo@BAR, and hence they need the same
   5047  1.1.1.2  christos 	 treatment.  */
   5048  1.1.1.2  christos       if (link_info->wrap_hash != NULL
   5049  1.1.1.2  christos 	  || sym_hash->versioned != unversioned)
   5050  1.1.1.2  christos 	{
   5051  1.1.1.2  christos 	  struct elf_link_hash_entry **cur_sym_hashes;
   5052  1.1.1.2  christos 
   5053  1.1.1.2  christos 	  /* Loop only over the symbols which have already been checked.  */
   5054  1.1.1.2  christos 	  for (cur_sym_hashes = sym_hashes; cur_sym_hashes < &sym_hashes[i];
   5055  1.1.1.2  christos 	       cur_sym_hashes++)
   5056  1.1.1.2  christos 	    {
   5057  1.1.1.2  christos 	      /* If the current symbol is identical to 'sym_hash', that means
   5058  1.1.1.2  christos 		 the symbol was already adjusted (or at least checked).  */
   5059  1.1.1.2  christos 	      if (*cur_sym_hashes == sym_hash)
   5060  1.1.1.2  christos 		break;
   5061  1.1.1.2  christos 	    }
   5062  1.1.1.2  christos 	  /* Don't adjust the symbol again.  */
   5063  1.1.1.2  christos 	  if (cur_sym_hashes < &sym_hashes[i])
   5064  1.1.1.2  christos 	    continue;
   5065  1.1.1.2  christos 	}
   5066  1.1.1.2  christos 
   5067  1.1.1.2  christos       if ((sym_hash->root.type == bfd_link_hash_defined
   5068  1.1.1.2  christos 	   || sym_hash->root.type == bfd_link_hash_defweak)
   5069  1.1.1.2  christos 	  && sym_hash->root.u.def.section == sec)
   5070  1.1.1.2  christos 	{
   5071  1.1.1.3  christos 	  bfd_vma orig_value = sym_hash->root.u.def.value;
   5072  1.1.1.3  christos 
   5073  1.1.1.3  christos 	  /* As above, adjust the value.  */
   5074  1.1.1.3  christos 	  if (orig_value <= toaddr)
   5075  1.1.1.3  christos 	    sym_hash->root.u.def.value
   5076  1.1.1.3  christos 		= loongarch_calc_relaxed_addr (link_info, orig_value);
   5077  1.1.1.2  christos 
   5078  1.1.1.2  christos 	  /* As above, adjust the size if needed.  */
   5079  1.1.1.3  christos 	  bfd_vma sym_end = orig_value + sym_hash->size;
   5080  1.1.1.3  christos 	  if (sym_end <= toaddr)
   5081  1.1.1.3  christos 	    {
   5082  1.1.1.3  christos 	      splay_tree_node node = splay_tree_predecessor (
   5083  1.1.1.3  christos 		  pdops, (splay_tree_key)orig_value);
   5084  1.1.1.3  christos 	      for (; node; node = splay_tree_successor (pdops, node->key))
   5085  1.1.1.3  christos 		{
   5086  1.1.1.3  christos 		  bfd_vma addr = (bfd_vma)node->key;
   5087  1.1.1.3  christos 		  struct pending_delete_op *op
   5088  1.1.1.3  christos 		      = (struct pending_delete_op *)node->value;
   5089  1.1.1.3  christos 
   5090  1.1.1.3  christos 		  if (addr >= sym_end)
   5091  1.1.1.3  christos 		    break;
   5092  1.1.1.3  christos 		  if (orig_value <= addr && sym_end > addr)
   5093  1.1.1.3  christos 		    sym_hash->size -= op->size;
   5094  1.1.1.3  christos 		}
   5095  1.1.1.3  christos 	    }
   5096  1.1.1.2  christos 	}
   5097  1.1.1.2  christos     }
   5098  1.1.1.3  christos }
   5099  1.1.1.2  christos 
   5100  1.1.1.3  christos /* Start perform TLS type transition.
   5101  1.1.1.3  christos    Currently there are three cases of relocation handled here:
   5102  1.1.1.3  christos    DESC -> IE, DEC -> LE and IE -> LE.  */
   5103  1.1.1.3  christos static bool
   5104  1.1.1.3  christos loongarch_tls_perform_trans (bfd *abfd, asection *sec,
   5105  1.1.1.3  christos 			   Elf_Internal_Rela *rel,
   5106  1.1.1.3  christos 			   struct elf_link_hash_entry *h,
   5107  1.1.1.3  christos 			   struct bfd_link_info *info)
   5108  1.1.1.3  christos {
   5109  1.1.1.3  christos   unsigned long insn;
   5110  1.1.1.3  christos   bool local_exec = bfd_link_executable (info)
   5111  1.1.1.3  christos 		      && LARCH_REF_LOCAL (info, h);
   5112  1.1.1.3  christos   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   5113  1.1.1.3  christos   unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
   5114  1.1.1.3  christos   unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
   5115  1.1.1.3  christos 
   5116  1.1.1.3  christos   switch (r_type)
   5117  1.1.1.3  christos     {
   5118  1.1.1.3  christos       case R_LARCH_TLS_DESC_PC_HI20:
   5119  1.1.1.3  christos 	if (local_exec)
   5120  1.1.1.3  christos 	  {
   5121  1.1.1.3  christos 	    /* DESC -> LE relaxation:
   5122  1.1.1.3  christos 	       pcalalau12i $a0,%desc_pc_hi20(var) =>
   5123  1.1.1.3  christos 	       lu12i.w $a0,%le_hi20(var)
   5124  1.1.1.3  christos 	    */
   5125  1.1.1.3  christos 	    bfd_put (32, abfd, LARCH_OP_LU12I_W | LARCH_RD_A0,
   5126  1.1.1.3  christos 		contents + rel->r_offset);
   5127  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_HI20);
   5128  1.1.1.3  christos 	  }
   5129  1.1.1.3  christos 	else
   5130  1.1.1.3  christos 	  {
   5131  1.1.1.3  christos 	    /* DESC -> IE relaxation:
   5132  1.1.1.3  christos 	       pcalalau12i $a0,%desc_pc_hi20(var) =>
   5133  1.1.1.3  christos 	       pcalalau12i $a0,%ie_pc_hi20(var)
   5134  1.1.1.3  christos 	    */
   5135  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_IE_PC_HI20);
   5136  1.1.1.3  christos 	  }
   5137  1.1.1.3  christos 	return true;
   5138  1.1.1.3  christos 
   5139  1.1.1.3  christos       case R_LARCH_TLS_DESC_PC_LO12:
   5140  1.1.1.3  christos 	if (local_exec)
   5141  1.1.1.3  christos 	  {
   5142  1.1.1.3  christos 	    /* DESC -> LE relaxation:
   5143  1.1.1.3  christos 	       addi.d $a0,$a0,%desc_pc_lo12(var) =>
   5144  1.1.1.3  christos 	       ori  $a0,$a0,le_lo12(var)
   5145  1.1.1.3  christos 	    */
   5146  1.1.1.3  christos 	    insn = LARCH_OP_ORI | LARCH_RD_RJ_A0;
   5147  1.1.1.3  christos 	    bfd_put (32, abfd, LARCH_OP_ORI | LARCH_RD_RJ_A0,
   5148  1.1.1.3  christos 		contents + rel->r_offset);
   5149  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_LO12);
   5150  1.1.1.3  christos 	  }
   5151  1.1.1.3  christos 	else
   5152  1.1.1.3  christos 	  {
   5153  1.1.1.3  christos 	    /* DESC -> IE relaxation:
   5154  1.1.1.3  christos 	       addi.d $a0,$a0,%desc_pc_lo12(var) =>
   5155  1.1.1.3  christos 	       ld.d $a0,$a0,%ie_pc_lo12(var)
   5156  1.1.1.3  christos 	    */
   5157  1.1.1.3  christos 	    bfd_put (32, abfd, LARCH_OP_LD_D | LARCH_RD_RJ_A0,
   5158  1.1.1.3  christos 		contents + rel->r_offset);
   5159  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_IE_PC_LO12);
   5160  1.1.1.3  christos 	  }
   5161  1.1.1.3  christos 	return true;
   5162  1.1.1.3  christos 
   5163  1.1.1.3  christos       case R_LARCH_TLS_DESC_LD:
   5164  1.1.1.3  christos       case R_LARCH_TLS_DESC_CALL:
   5165  1.1.1.3  christos 	/* DESC -> LE/IE relaxation:
   5166  1.1.1.3  christos 	   ld.d $ra,$a0,%desc_ld(var) => NOP
   5167  1.1.1.3  christos 	   jirl $ra,$ra,%desc_call(var) => NOP
   5168  1.1.1.3  christos 	*/
   5169  1.1.1.3  christos 	rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
   5170  1.1.1.3  christos 	bfd_put (32, abfd, LARCH_NOP, contents + rel->r_offset);
   5171  1.1.1.3  christos 	/* link with -relax option will delete NOP.  */
   5172  1.1.1.3  christos 	if (!info->disable_target_specific_optimizations)
   5173  1.1.1.3  christos 	  loongarch_relax_delete_or_nop (abfd, sec, rel->r_offset, 4, info);
   5174  1.1.1.3  christos 	return true;
   5175  1.1.1.3  christos 
   5176  1.1.1.3  christos       case R_LARCH_TLS_IE_PC_HI20:
   5177  1.1.1.3  christos 	if (local_exec)
   5178  1.1.1.3  christos 	  {
   5179  1.1.1.3  christos 	    /* IE -> LE relaxation:
   5180  1.1.1.3  christos 	       pcalalau12i $rd,%ie_pc_hi20(var) =>
   5181  1.1.1.3  christos 	       lu12i.w $rd,%le_hi20(var)
   5182  1.1.1.3  christos 	    */
   5183  1.1.1.3  christos 	    insn = bfd_getl32 (contents + rel->r_offset);
   5184  1.1.1.3  christos 	    bfd_put (32, abfd, LARCH_OP_LU12I_W | LARCH_GET_RD(insn),
   5185  1.1.1.3  christos 		contents + rel->r_offset);
   5186  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_HI20);
   5187  1.1.1.3  christos 	  }
   5188  1.1.1.3  christos 	return true;
   5189  1.1.1.3  christos 
   5190  1.1.1.3  christos       case R_LARCH_TLS_IE_PC_LO12:
   5191  1.1.1.3  christos 	if (local_exec)
   5192  1.1.1.3  christos 	  {
   5193  1.1.1.3  christos 	    /* IE -> LE relaxation:
   5194  1.1.1.3  christos 	       ld.d $rd,$rj,%%ie_pc_lo12(var) =>
   5195  1.1.1.3  christos 	       ori  $rd,$rj,le_lo12(var)
   5196  1.1.1.3  christos 	    */
   5197  1.1.1.3  christos 	    insn = bfd_getl32 (contents + rel->r_offset);
   5198  1.1.1.3  christos 	    bfd_put (32, abfd, LARCH_OP_ORI | (insn & 0x3ff),
   5199  1.1.1.3  christos 		contents + rel->r_offset);
   5200  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_LO12);
   5201  1.1.1.3  christos 	  }
   5202  1.1.1.3  christos 	return true;
   5203  1.1.1.3  christos     }
   5204  1.1.1.3  christos 
   5205  1.1.1.3  christos   return false;
   5206  1.1.1.2  christos }
   5207  1.1.1.3  christos 
   5208  1.1.1.3  christos 
   5209  1.1.1.2  christos /*  Relax tls le, mainly relax the process of getting TLS le symbolic addresses.
   5210  1.1.1.2  christos   there are three situations in which an assembly instruction sequence needs to
   5211  1.1.1.2  christos   be relaxed:
   5212  1.1.1.2  christos   symbol address = tp + offset (symbol),offset (symbol) = le_hi20_r + le_lo12_r
   5213  1.1.1.2  christos 
   5214  1.1.1.2  christos   Case 1:
   5215  1.1.1.2  christos   in this case, the rd register in the st.{w/d} instruction does not store the
   5216  1.1.1.2  christos   full tls symbolic address, but tp + le_hi20_r, which is a part of the tls
   5217  1.1.1.2  christos   symbolic address, and then obtains the rd + le_lo12_r address through the
   5218  1.1.1.2  christos   st.w instruction feature.
   5219  1.1.1.2  christos   this is the full tls symbolic address (tp + le_hi20_r + le_lo12_r).
   5220  1.1.1.2  christos 
   5221  1.1.1.2  christos   before relax:				after relax:
   5222  1.1.1.2  christos 
   5223  1.1.1.2  christos   lu12i.w   $rd,%le_hi20_r (sym)	==> (instruction deleted)
   5224  1.1.1.2  christos   add.{w/d} $rd,$rd,$tp,%le_add_r (sym) ==> (instruction deleted)
   5225  1.1.1.2  christos   st.{w/d}  $rs,$rd,%le_lo12_r (sym)    ==> st.{w/d}   $rs,$tp,%le_lo12_r (sym)
   5226  1.1.1.2  christos 
   5227  1.1.1.2  christos   Case 2:
   5228  1.1.1.2  christos   in this case, ld.{w/d} is similar to st.{w/d} in case1.
   5229  1.1.1.2  christos 
   5230  1.1.1.2  christos   before relax:				after relax:
   5231  1.1.1.2  christos 
   5232  1.1.1.2  christos   lu12i.w   $rd,%le_hi20_r (sym)	==> (instruction deleted)
   5233  1.1.1.2  christos   add.{w/d} $rd,$rd,$tp,%le_add_r (sym) ==> (instruction deleted)
   5234  1.1.1.2  christos   ld.{w/d}  $rs,$rd,%le_lo12_r (sym)    ==> ld.{w/d}   $rs,$tp,%le_lo12_r (sym)
   5235  1.1.1.2  christos 
   5236  1.1.1.2  christos   Case 3:
   5237  1.1.1.2  christos   in this case,the rs register in addi.{w/d} stores the full address of the tls
   5238  1.1.1.2  christos   symbol (tp + le_hi20_r + le_lo12_r).
   5239  1.1.1.2  christos 
   5240  1.1.1.2  christos   before relax:				after relax:
   5241  1.1.1.2  christos 
   5242  1.1.1.2  christos   lu12i.w    $rd,%le_hi20_r (sym)	 ==> (instruction deleted)
   5243  1.1.1.2  christos   add.{w/d}  $rd,$rd,$tp,%le_add_r (sym) ==> (instruction deleted)
   5244  1.1.1.2  christos   addi.{w/d} $rs,$rd,%le_lo12_r (sym)    ==> addi.{w/d} $rs,$tp,%le_lo12_r (sym)
   5245  1.1.1.3  christos 
   5246  1.1.1.3  christos 
   5247  1.1.1.3  christos   For relocation of all old LE instruction sequences, whether it is
   5248  1.1.1.3  christos   a normal code model or an extreme code model, relaxation will be
   5249  1.1.1.3  christos   performed when the relaxation conditions are met.
   5250  1.1.1.3  christos 
   5251  1.1.1.3  christos   nomal code model:
   5252  1.1.1.3  christos   lu12i.w   $rd,%le_hi20(sym)	    => (deleted)
   5253  1.1.1.3  christos   ori	    $rd,$rd,le_lo12(sym)    => ori  $rd,$zero,le_lo12(sym)
   5254  1.1.1.3  christos 
   5255  1.1.1.3  christos   extreme code model:
   5256  1.1.1.3  christos   lu12i.w   $rd,%le_hi20(sym)	    => (deleted)
   5257  1.1.1.3  christos   ori	    $rd,$rd,%le_lo12(sym)   => ori  $rd,$zero,le_lo12(sym)
   5258  1.1.1.3  christos   lu32i.d   $rd,%le64_lo20(sym)	    => (deleted)
   5259  1.1.1.3  christos   lu52i.d   $rd,$rd,%le64_hi12(sym) => (deleted)
   5260  1.1.1.2  christos */
   5261  1.1.1.2  christos static bool
   5262  1.1.1.3  christos loongarch_relax_tls_le (bfd *abfd, asection *sec, asection *sym_sec,
   5263  1.1.1.3  christos 			Elf_Internal_Rela *rel, bfd_vma symval,
   5264  1.1.1.2  christos 			struct bfd_link_info *link_info,
   5265  1.1.1.3  christos 			bool *agin ATTRIBUTE_UNUSED,
   5266  1.1.1.3  christos 			bfd_vma max_alignment ATTRIBUTE_UNUSED)
   5267  1.1.1.2  christos {
   5268  1.1.1.2  christos   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   5269  1.1.1.2  christos   uint32_t insn = bfd_get (32, abfd, contents + rel->r_offset);
   5270  1.1.1.2  christos   static uint32_t insn_rj,insn_rd;
   5271  1.1.1.2  christos   symval = symval - elf_hash_table (link_info)->tls_sec->vma;
   5272  1.1.1.3  christos   if (sym_sec == sec)
   5273  1.1.1.3  christos     symval = loongarch_calc_relaxed_addr (link_info, symval);
   5274  1.1.1.3  christos   /* The old LE instruction sequence can be relaxed when the symbol offset
   5275  1.1.1.3  christos      is smaller than the 12-bit range.  */
   5276  1.1.1.3  christos   if (symval <= 0xfff)
   5277  1.1.1.2  christos     {
   5278  1.1.1.2  christos       switch (ELFNN_R_TYPE (rel->r_info))
   5279  1.1.1.2  christos 	{
   5280  1.1.1.3  christos 	  /*if offset < 0x800, then perform the new le instruction
   5281  1.1.1.3  christos 	    sequence relax.  */
   5282  1.1.1.3  christos 	  case R_LARCH_TLS_LE_HI20_R:
   5283  1.1.1.3  christos 	  case R_LARCH_TLS_LE_ADD_R:
   5284  1.1.1.3  christos 	    /* delete insn.  */
   5285  1.1.1.3  christos 	    if (symval < 0x800)
   5286  1.1.1.3  christos 	      {
   5287  1.1.1.3  christos 		rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
   5288  1.1.1.3  christos 		loongarch_relax_delete_or_nop (abfd, sec, rel->r_offset,
   5289  1.1.1.3  christos 		    4, link_info);
   5290  1.1.1.3  christos 	      }
   5291  1.1.1.3  christos 	    break;
   5292  1.1.1.3  christos 
   5293  1.1.1.3  christos 	  case R_LARCH_TLS_LE_LO12_R:
   5294  1.1.1.3  christos 	    if (symval < 0x800)
   5295  1.1.1.3  christos 	      {
   5296  1.1.1.3  christos 		/* Change rj to $tp.  */
   5297  1.1.1.3  christos 		insn_rj = 0x2 << 5;
   5298  1.1.1.3  christos 		/* Get rd register.  */
   5299  1.1.1.3  christos 		insn_rd = LARCH_GET_RD (insn);
   5300  1.1.1.3  christos 		/* Write symbol offset.  */
   5301  1.1.1.3  christos 		symval <<= 10;
   5302  1.1.1.3  christos 		/* Writes the modified instruction.  */
   5303  1.1.1.3  christos 		insn = insn & LARCH_MK_ADDI_D;
   5304  1.1.1.3  christos 		insn = insn | symval | insn_rj | insn_rd;
   5305  1.1.1.3  christos 		bfd_put (32, abfd, insn, contents + rel->r_offset);
   5306  1.1.1.3  christos 	      }
   5307  1.1.1.3  christos 	    break;
   5308  1.1.1.3  christos 
   5309  1.1.1.3  christos 	  case R_LARCH_TLS_LE_HI20:
   5310  1.1.1.3  christos 	  case R_LARCH_TLS_LE64_LO20:
   5311  1.1.1.3  christos 	  case R_LARCH_TLS_LE64_HI12:
   5312  1.1.1.3  christos 	    rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
   5313  1.1.1.3  christos 	    loongarch_relax_delete_or_nop (abfd, sec, rel->r_offset,
   5314  1.1.1.3  christos 					   4, link_info);
   5315  1.1.1.3  christos 	    break;
   5316  1.1.1.3  christos 
   5317  1.1.1.3  christos 	  case R_LARCH_TLS_LE_LO12:
   5318  1.1.1.3  christos 	    bfd_put (32, abfd, LARCH_OP_ORI | LARCH_GET_RD (insn),
   5319  1.1.1.3  christos 		    contents + rel->r_offset);
   5320  1.1.1.3  christos 	    break;
   5321  1.1.1.3  christos 
   5322  1.1.1.3  christos 	  default:
   5323  1.1.1.3  christos 	    break;
   5324  1.1.1.2  christos 	}
   5325  1.1.1.2  christos     }
   5326  1.1.1.2  christos   return true;
   5327  1.1.1.2  christos }
   5328  1.1.1.2  christos 
   5329  1.1.1.3  christos /* Whether two sections in the same segment.  */
   5330  1.1.1.3  christos static bool
   5331  1.1.1.3  christos loongarch_two_sections_in_same_segment (bfd *abfd, asection *a, asection *b)
   5332  1.1.1.3  christos {
   5333  1.1.1.3  christos   struct elf_segment_map *m;
   5334  1.1.1.3  christos   for (m = elf_seg_map (abfd); m != NULL; m = m->next)
   5335  1.1.1.3  christos     {
   5336  1.1.1.3  christos       int i;
   5337  1.1.1.3  christos       int j = 0;
   5338  1.1.1.3  christos       for (i = m->count - 1; i >= 0; i--)
   5339  1.1.1.3  christos 	{
   5340  1.1.1.3  christos 	  if (m->sections[i] == a)
   5341  1.1.1.3  christos 	    j++;
   5342  1.1.1.3  christos 	  if (m->sections[i] == b)
   5343  1.1.1.3  christos 	    j++;
   5344  1.1.1.3  christos 	}
   5345  1.1.1.3  christos       if (1 == j)
   5346  1.1.1.3  christos 	return false;
   5347  1.1.1.3  christos       if (2 == j)
   5348  1.1.1.3  christos 	return true;
   5349  1.1.1.3  christos     }
   5350  1.1.1.3  christos   return false;
   5351  1.1.1.3  christos }
   5352  1.1.1.3  christos 
   5353  1.1.1.2  christos /* Relax pcalau12i,addi.d => pcaddi.  */
   5354  1.1.1.2  christos static bool
   5355  1.1.1.2  christos loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
   5356  1.1.1.2  christos 			    Elf_Internal_Rela *rel_hi, bfd_vma symval,
   5357  1.1.1.2  christos 			    struct bfd_link_info *info, bool *again,
   5358  1.1.1.2  christos 			    bfd_vma max_alignment)
   5359  1.1.1.2  christos {
   5360  1.1.1.2  christos   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   5361  1.1.1.2  christos   Elf_Internal_Rela *rel_lo = rel_hi + 2;
   5362  1.1.1.2  christos   uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
   5363  1.1.1.2  christos   uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
   5364  1.1.1.3  christos   uint32_t rd = LARCH_GET_RD (pca);
   5365  1.1.1.2  christos 
   5366  1.1.1.2  christos   /* This section's output_offset need to subtract the bytes of instructions
   5367  1.1.1.2  christos      relaxed by the previous sections, so it needs to be updated beforehand.
   5368  1.1.1.2  christos      size_input_section already took care of updating it after relaxation,
   5369  1.1.1.2  christos      so we additionally update once here.  */
   5370  1.1.1.2  christos   sec->output_offset = sec->output_section->size;
   5371  1.1.1.3  christos   bfd_vma pc = sec_addr (sec)
   5372  1.1.1.3  christos 	       + loongarch_calc_relaxed_addr (info, rel_hi->r_offset);
   5373  1.1.1.3  christos   if (sym_sec == sec)
   5374  1.1.1.3  christos     symval = sec_addr (sec)
   5375  1.1.1.3  christos 	     + loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
   5376  1.1.1.3  christos 
   5377  1.1.1.3  christos   /* If pc and symbol not in the same segment, add/sub segment alignment.  */
   5378  1.1.1.3  christos   if (!loongarch_two_sections_in_same_segment (info->output_bfd,
   5379  1.1.1.3  christos 					       sec->output_section,
   5380  1.1.1.3  christos 					       sym_sec->output_section))
   5381  1.1.1.3  christos     max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize
   5382  1.1.1.3  christos 						      : max_alignment;
   5383  1.1.1.3  christos 
   5384  1.1.1.3  christos   if (symval > pc)
   5385  1.1.1.3  christos     pc -= (max_alignment > 4 ? max_alignment : 0);
   5386  1.1.1.3  christos   else if (symval < pc)
   5387  1.1.1.3  christos     pc += (max_alignment > 4 ? max_alignment : 0);
   5388  1.1.1.2  christos 
   5389  1.1.1.3  christos   const uint32_t pcaddi = LARCH_OP_PCADDI;
   5390  1.1.1.2  christos 
   5391  1.1.1.2  christos   /* Is pcalau12i + addi.d insns?  */
   5392  1.1.1.2  christos   if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12)
   5393  1.1.1.3  christos       || !LARCH_INSN_ADDI_D (add)
   5394  1.1.1.2  christos       /* Is pcalau12i $rd + addi.d $rd,$rd?  */
   5395  1.1.1.3  christos       || (LARCH_GET_RD (add) != rd)
   5396  1.1.1.3  christos       || (LARCH_GET_RJ (add) != rd)
   5397  1.1.1.2  christos       /* Can be relaxed to pcaddi?  */
   5398  1.1.1.2  christos       || (symval & 0x3) /* 4 bytes align.  */
   5399  1.1.1.2  christos       || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
   5400  1.1.1.2  christos       || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x1ffffc))
   5401  1.1.1.2  christos     return false;
   5402  1.1.1.2  christos 
   5403  1.1.1.2  christos   /* Continue next relax trip.  */
   5404  1.1.1.2  christos   *again = true;
   5405  1.1.1.2  christos 
   5406  1.1.1.2  christos   pca = pcaddi | rd;
   5407  1.1.1.2  christos   bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
   5408  1.1.1.2  christos 
   5409  1.1.1.2  christos   /* Adjust relocations.  */
   5410  1.1.1.2  christos   rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
   5411  1.1.1.2  christos 				 R_LARCH_PCREL20_S2);
   5412  1.1.1.2  christos   rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
   5413  1.1.1.2  christos 
   5414  1.1.1.3  christos   loongarch_relax_delete_or_nop (abfd, sec, rel_lo->r_offset, 4, info);
   5415  1.1.1.2  christos 
   5416  1.1.1.2  christos   return true;
   5417  1.1.1.2  christos }
   5418  1.1.1.2  christos 
   5419  1.1.1.3  christos /* call36 f -> bl f
   5420  1.1.1.3  christos    tail36 $t0, f -> b f.  */
   5421  1.1.1.3  christos static bool
   5422  1.1.1.3  christos loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
   5423  1.1.1.3  christos 			    Elf_Internal_Rela *rel, bfd_vma symval,
   5424  1.1.1.3  christos 			    struct bfd_link_info *info, bool *again,
   5425  1.1.1.3  christos 			    bfd_vma max_alignment)
   5426  1.1.1.3  christos {
   5427  1.1.1.3  christos   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   5428  1.1.1.3  christos   uint32_t jirl = bfd_get (32, abfd, contents + rel->r_offset + 4);
   5429  1.1.1.3  christos   uint32_t rd = LARCH_GET_RD (jirl);
   5430  1.1.1.3  christos 
   5431  1.1.1.3  christos   /* This section's output_offset need to subtract the bytes of instructions
   5432  1.1.1.3  christos      relaxed by the previous sections, so it needs to be updated beforehand.
   5433  1.1.1.3  christos      size_input_section already took care of updating it after relaxation,
   5434  1.1.1.3  christos      so we additionally update once here.  */
   5435  1.1.1.3  christos   sec->output_offset = sec->output_section->size;
   5436  1.1.1.3  christos   bfd_vma pc = sec_addr (sec)
   5437  1.1.1.3  christos 	       + loongarch_calc_relaxed_addr (info, rel->r_offset);
   5438  1.1.1.3  christos   if (sym_sec == sec)
   5439  1.1.1.3  christos     symval = sec_addr (sec)
   5440  1.1.1.3  christos 	     + loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
   5441  1.1.1.3  christos 
   5442  1.1.1.3  christos   /* If pc and symbol not in the same segment, add/sub segment alignment.  */
   5443  1.1.1.3  christos   if (!loongarch_two_sections_in_same_segment (info->output_bfd,
   5444  1.1.1.3  christos 					       sec->output_section,
   5445  1.1.1.3  christos 					       sym_sec->output_section))
   5446  1.1.1.3  christos     max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize
   5447  1.1.1.3  christos 						      : max_alignment;
   5448  1.1.1.3  christos 
   5449  1.1.1.3  christos   if (symval > pc)
   5450  1.1.1.3  christos     pc -= (max_alignment > 4 ? max_alignment : 0);
   5451  1.1.1.3  christos   else if (symval < pc)
   5452  1.1.1.3  christos     pc += (max_alignment > 4 ? max_alignment : 0);
   5453  1.1.1.3  christos 
   5454  1.1.1.3  christos   /* Is pcalau12i + addi.d insns?  */
   5455  1.1.1.3  christos   if (!LARCH_INSN_JIRL (jirl)
   5456  1.1.1.3  christos       || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xf8000000)
   5457  1.1.1.3  christos       || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffc))
   5458  1.1.1.3  christos     return false;
   5459  1.1.1.3  christos 
   5460  1.1.1.3  christos   /* Continue next relax trip.  */
   5461  1.1.1.3  christos   *again = true;
   5462  1.1.1.3  christos 
   5463  1.1.1.3  christos   const uint32_t bl = LARCH_OP_BL;
   5464  1.1.1.3  christos   const uint32_t b = LARCH_OP_B;
   5465  1.1.1.3  christos 
   5466  1.1.1.3  christos   if (rd)
   5467  1.1.1.3  christos     bfd_put (32, abfd, bl, contents + rel->r_offset);
   5468  1.1.1.3  christos   else
   5469  1.1.1.3  christos     bfd_put (32, abfd, b, contents + rel->r_offset);
   5470  1.1.1.3  christos 
   5471  1.1.1.3  christos   /* Adjust relocations.  */
   5472  1.1.1.3  christos   rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_LARCH_B26);
   5473  1.1.1.3  christos   /* Delete jirl instruction.  */
   5474  1.1.1.3  christos   loongarch_relax_delete_or_nop (abfd, sec, rel->r_offset + 4, 4, info);
   5475  1.1.1.3  christos   return true;
   5476  1.1.1.3  christos }
   5477  1.1.1.3  christos 
   5478  1.1.1.2  christos /* Relax pcalau12i,ld.d => pcalau12i,addi.d.  */
   5479  1.1.1.2  christos static bool
   5480  1.1.1.2  christos loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
   5481  1.1.1.3  christos 			  asection *sym_sec,
   5482  1.1.1.3  christos 			  Elf_Internal_Rela *rel_hi,
   5483  1.1.1.3  christos 			  bfd_vma symval,
   5484  1.1.1.3  christos 			  struct bfd_link_info *info,
   5485  1.1.1.3  christos 			  bool *again ATTRIBUTE_UNUSED,
   5486  1.1.1.3  christos 			  bfd_vma max_alignment)
   5487  1.1.1.2  christos {
   5488  1.1.1.2  christos   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   5489  1.1.1.2  christos   Elf_Internal_Rela *rel_lo = rel_hi + 2;
   5490  1.1.1.2  christos   uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
   5491  1.1.1.2  christos   uint32_t ld = bfd_get (32, abfd, contents + rel_lo->r_offset);
   5492  1.1.1.3  christos   uint32_t rd = LARCH_GET_RD (pca);
   5493  1.1.1.3  christos   uint32_t addi_d = LARCH_OP_ADDI_D;
   5494  1.1.1.3  christos 
   5495  1.1.1.3  christos   /* This section's output_offset need to subtract the bytes of instructions
   5496  1.1.1.3  christos      relaxed by the previous sections, so it needs to be updated beforehand.
   5497  1.1.1.3  christos      size_input_section already took care of updating it after relaxation,
   5498  1.1.1.3  christos      so we additionally update once here.  */
   5499  1.1.1.3  christos   sec->output_offset = sec->output_section->size;
   5500  1.1.1.3  christos   bfd_vma pc = sec_addr (sec)
   5501  1.1.1.3  christos 	       + loongarch_calc_relaxed_addr (info, rel_hi->r_offset);
   5502  1.1.1.3  christos   if (sym_sec == sec)
   5503  1.1.1.3  christos     symval = sec_addr (sec)
   5504  1.1.1.3  christos 	     + loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
   5505  1.1.1.3  christos 
   5506  1.1.1.3  christos   /* If pc and symbol not in the same segment, add/sub segment alignment.  */
   5507  1.1.1.3  christos   if (!loongarch_two_sections_in_same_segment (info->output_bfd,
   5508  1.1.1.3  christos 					       sec->output_section,
   5509  1.1.1.3  christos 					       sym_sec->output_section))
   5510  1.1.1.3  christos     max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize
   5511  1.1.1.3  christos 						      : max_alignment;
   5512  1.1.1.3  christos 
   5513  1.1.1.3  christos   if (symval > pc)
   5514  1.1.1.3  christos     pc -= (max_alignment > 4 ? max_alignment : 0);
   5515  1.1.1.3  christos   else if (symval < pc)
   5516  1.1.1.3  christos     pc += (max_alignment > 4 ? max_alignment : 0);
   5517  1.1.1.2  christos 
   5518  1.1.1.2  christos   if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
   5519  1.1.1.3  christos       || (LARCH_GET_RD (ld) != rd)
   5520  1.1.1.3  christos       || (LARCH_GET_RJ (ld) != rd)
   5521  1.1.1.3  christos       || !LARCH_INSN_LD_D (ld)
   5522  1.1.1.3  christos       /* Within +-2G addressing range.  */
   5523  1.1.1.3  christos       || (bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0x80000000
   5524  1.1.1.3  christos       || (bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffff)
   5525  1.1.1.2  christos     return false;
   5526  1.1.1.2  christos 
   5527  1.1.1.2  christos   addi_d = addi_d | (rd << 5) | rd;
   5528  1.1.1.2  christos   bfd_put (32, abfd, addi_d, contents + rel_lo->r_offset);
   5529  1.1.1.2  christos 
   5530  1.1.1.2  christos   rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
   5531  1.1.1.2  christos 				 R_LARCH_PCALA_HI20);
   5532  1.1.1.2  christos   rel_lo->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_lo->r_info),
   5533  1.1.1.2  christos 				 R_LARCH_PCALA_LO12);
   5534  1.1.1.2  christos   return true;
   5535  1.1.1.2  christos }
   5536  1.1.1.2  christos 
   5537  1.1.1.2  christos /* Called by after_allocation to set the information of data segment
   5538  1.1.1.2  christos    before relaxing.  */
   5539  1.1.1.2  christos 
   5540  1.1.1.2  christos void
   5541  1.1.1.2  christos bfd_elfNN_loongarch_set_data_segment_info (struct bfd_link_info *info,
   5542  1.1.1.2  christos 				     int *data_segment_phase)
   5543  1.1.1.2  christos {
   5544  1.1.1.3  christos   if (is_elf_hash_table (info->hash)
   5545  1.1.1.3  christos       && elf_hash_table_id (elf_hash_table (info)) == LARCH_ELF_DATA)
   5546  1.1.1.3  christos     loongarch_elf_hash_table (info)->data_segment_phase = data_segment_phase;
   5547  1.1.1.2  christos }
   5548  1.1.1.2  christos 
   5549  1.1.1.3  christos /* Honor R_LARCH_ALIGN requests by deleting excess alignment NOPs.
   5550  1.1.1.3  christos    Once we've handled an R_LARCH_ALIGN, we can't relax anything else by deleting
   5551  1.1.1.3  christos    bytes, or alignment will be disrupted.  */
   5552  1.1.1.2  christos static bool
   5553  1.1.1.3  christos loongarch_relax_align (bfd *abfd, asection *sec, asection *sym_sec,
   5554  1.1.1.2  christos 			Elf_Internal_Rela *rel,
   5555  1.1.1.3  christos 			bfd_vma symval,
   5556  1.1.1.3  christos 			struct bfd_link_info *link_info,
   5557  1.1.1.3  christos 			bool *again ATTRIBUTE_UNUSED,
   5558  1.1.1.3  christos 			bfd_vma max_alignment ATTRIBUTE_UNUSED)
   5559  1.1.1.2  christos {
   5560  1.1.1.2  christos   bfd_vma  addend, max = 0, alignment = 1;
   5561  1.1.1.2  christos 
   5562  1.1.1.2  christos   int sym_index = ELFNN_R_SYM (rel->r_info);
   5563  1.1.1.2  christos   if (sym_index > 0)
   5564  1.1.1.2  christos     {
   5565  1.1.1.2  christos       alignment = 1 << (rel->r_addend & 0xff);
   5566  1.1.1.2  christos       max = rel->r_addend >> 8;
   5567  1.1.1.2  christos     }
   5568  1.1.1.2  christos   else
   5569  1.1.1.2  christos     alignment = rel->r_addend + 4;
   5570  1.1.1.2  christos 
   5571  1.1.1.3  christos   if (sym_sec == sec)
   5572  1.1.1.3  christos     symval = sec_addr (sec)
   5573  1.1.1.3  christos 	     + loongarch_calc_relaxed_addr (link_info, symval - sec_addr (sec));
   5574  1.1.1.3  christos 
   5575  1.1.1.2  christos   addend = alignment - 4; /* The bytes of NOPs added by R_LARCH_ALIGN.  */
   5576  1.1.1.2  christos   symval -= addend; /* The address of first NOP added by R_LARCH_ALIGN.  */
   5577  1.1.1.2  christos   bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
   5578  1.1.1.2  christos   bfd_vma need_nop_bytes = aligned_addr - symval; /* */
   5579  1.1.1.2  christos 
   5580  1.1.1.2  christos   /* Make sure there are enough NOPs to actually achieve the alignment.  */
   5581  1.1.1.2  christos   if (addend < need_nop_bytes)
   5582  1.1.1.2  christos     {
   5583  1.1.1.2  christos       _bfd_error_handler
   5584  1.1.1.2  christos 	(_("%pB(%pA+%#" PRIx64 "): %" PRId64 " bytes required for alignment "
   5585  1.1.1.2  christos 	   "to %" PRId64 "-byte boundary, but only %" PRId64 " present"),
   5586  1.1.1.2  christos 	 abfd, sym_sec, (uint64_t) rel->r_offset,
   5587  1.1.1.2  christos 	 (int64_t) need_nop_bytes, (int64_t) alignment, (int64_t) addend);
   5588  1.1.1.2  christos       bfd_set_error (bfd_error_bad_value);
   5589  1.1.1.2  christos       return false;
   5590  1.1.1.2  christos     }
   5591  1.1.1.2  christos 
   5592  1.1.1.3  christos   /* Once we've handled an R_LARCH_ALIGN in a section, we can't relax anything
   5593  1.1.1.3  christos      else by deleting bytes, or alignment will be disrupted.  */
   5594  1.1.1.3  christos   loongarch_sec_closed_for_deletion (sec) = true;
   5595  1.1.1.2  christos   rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
   5596  1.1.1.2  christos 
   5597  1.1.1.2  christos   /* If skipping more bytes than the specified maximum,
   5598  1.1.1.2  christos      then the alignment is not done at all and delete all NOPs.  */
   5599  1.1.1.2  christos   if (max > 0 && need_nop_bytes > max)
   5600  1.1.1.3  christos     {
   5601  1.1.1.3  christos       loongarch_relax_delete_bytes (abfd, rel->r_offset, addend, link_info);
   5602  1.1.1.3  christos       return true;
   5603  1.1.1.3  christos     }
   5604  1.1.1.2  christos 
   5605  1.1.1.2  christos   /* If the number of NOPs is already correct, there's nothing to do.  */
   5606  1.1.1.2  christos   if (need_nop_bytes == addend)
   5607  1.1.1.2  christos     return true;
   5608  1.1.1.2  christos 
   5609  1.1.1.2  christos   /* Delete the excess NOPs.  */
   5610  1.1.1.3  christos   loongarch_relax_delete_bytes (abfd, rel->r_offset + need_nop_bytes,
   5611  1.1.1.3  christos 				addend - need_nop_bytes, link_info);
   5612  1.1.1.3  christos   return true;
   5613  1.1.1.2  christos }
   5614  1.1.1.2  christos 
   5615  1.1.1.2  christos /* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
   5616  1.1.1.2  christos static bool
   5617  1.1.1.2  christos loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
   5618  1.1.1.2  christos 				Elf_Internal_Rela *rel_hi, bfd_vma symval,
   5619  1.1.1.2  christos 				struct bfd_link_info *info, bool *again,
   5620  1.1.1.2  christos 				bfd_vma max_alignment)
   5621  1.1.1.2  christos {
   5622  1.1.1.2  christos   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
   5623  1.1.1.2  christos   Elf_Internal_Rela *rel_lo = rel_hi + 2;
   5624  1.1.1.2  christos   uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
   5625  1.1.1.2  christos   uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
   5626  1.1.1.3  christos   uint32_t rd = LARCH_GET_RD (pca);
   5627  1.1.1.2  christos 
   5628  1.1.1.2  christos   /* This section's output_offset need to subtract the bytes of instructions
   5629  1.1.1.2  christos      relaxed by the previous sections, so it needs to be updated beforehand.
   5630  1.1.1.2  christos      size_input_section already took care of updating it after relaxation,
   5631  1.1.1.2  christos      so we additionally update once here.  */
   5632  1.1.1.2  christos   sec->output_offset = sec->output_section->size;
   5633  1.1.1.3  christos   bfd_vma pc = sec_addr (sec)
   5634  1.1.1.3  christos 	       + loongarch_calc_relaxed_addr (info, rel_hi->r_offset);
   5635  1.1.1.3  christos   if (sym_sec == sec)
   5636  1.1.1.3  christos     symval = sec_addr (sec)
   5637  1.1.1.3  christos 	     + loongarch_calc_relaxed_addr (info, symval - sec_addr (sec));
   5638  1.1.1.3  christos 
   5639  1.1.1.3  christos   /* If pc and symbol not in the same segment, add/sub segment alignment.  */
   5640  1.1.1.3  christos   if (!loongarch_two_sections_in_same_segment (info->output_bfd,
   5641  1.1.1.3  christos 					       sec->output_section,
   5642  1.1.1.3  christos 					       sym_sec->output_section))
   5643  1.1.1.3  christos     max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize
   5644  1.1.1.3  christos 						      : max_alignment;
   5645  1.1.1.3  christos 
   5646  1.1.1.3  christos   if (symval > pc)
   5647  1.1.1.3  christos     pc -= (max_alignment > 4 ? max_alignment : 0);
   5648  1.1.1.3  christos   else if (symval < pc)
   5649  1.1.1.3  christos     pc += (max_alignment > 4 ? max_alignment : 0);
   5650  1.1.1.2  christos 
   5651  1.1.1.3  christos   const uint32_t pcaddi = LARCH_OP_PCADDI;
   5652  1.1.1.2  christos 
   5653  1.1.1.2  christos   /* Is pcalau12i + addi.d insns?  */
   5654  1.1.1.2  christos   if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12
   5655  1.1.1.2  christos 	&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_PC_LO12)
   5656  1.1.1.3  christos       || !LARCH_INSN_ADDI_D (add)
   5657  1.1.1.2  christos       /* Is pcalau12i $rd + addi.d $rd,$rd?  */
   5658  1.1.1.3  christos       || (LARCH_GET_RD (add) != rd)
   5659  1.1.1.3  christos       || (LARCH_GET_RJ (add) != rd)
   5660  1.1.1.2  christos       /* Can be relaxed to pcaddi?  */
   5661  1.1.1.2  christos       || (symval & 0x3) /* 4 bytes align.  */
   5662  1.1.1.2  christos       || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
   5663  1.1.1.2  christos       || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x1ffffc))
   5664  1.1.1.2  christos     return false;
   5665  1.1.1.2  christos 
   5666  1.1.1.2  christos   /* Continue next relax trip.  */
   5667  1.1.1.2  christos   *again = true;
   5668  1.1.1.2  christos 
   5669  1.1.1.2  christos   pca = pcaddi | rd;
   5670  1.1.1.2  christos   bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
   5671  1.1.1.2  christos 
   5672  1.1.1.2  christos   /* Adjust relocations.  */
   5673  1.1.1.2  christos   switch (ELFNN_R_TYPE (rel_hi->r_info))
   5674  1.1.1.2  christos     {
   5675  1.1.1.2  christos     case R_LARCH_TLS_LD_PC_HI20:
   5676  1.1.1.2  christos       rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
   5677  1.1.1.2  christos 				      R_LARCH_TLS_LD_PCREL20_S2);
   5678  1.1.1.2  christos       break;
   5679  1.1.1.2  christos     case R_LARCH_TLS_GD_PC_HI20:
   5680  1.1.1.2  christos       rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
   5681  1.1.1.2  christos 				      R_LARCH_TLS_GD_PCREL20_S2);
   5682  1.1.1.2  christos       break;
   5683  1.1.1.2  christos     case R_LARCH_TLS_DESC_PC_HI20:
   5684  1.1.1.2  christos       rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
   5685  1.1.1.2  christos 				      R_LARCH_TLS_DESC_PCREL20_S2);
   5686  1.1.1.2  christos       break;
   5687  1.1.1.2  christos     default:
   5688  1.1.1.2  christos       break;
   5689  1.1.1.2  christos     }
   5690  1.1.1.2  christos   rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
   5691  1.1.1.2  christos 
   5692  1.1.1.3  christos   loongarch_relax_delete_or_nop (abfd, sec, rel_lo->r_offset, 4, info);
   5693  1.1.1.2  christos 
   5694  1.1.1.2  christos   return true;
   5695  1.1.1.2  christos }
   5696  1.1.1.2  christos 
   5697  1.1.1.2  christos /* Traverse all output sections and return the max alignment.  */
   5698  1.1.1.2  christos 
   5699  1.1.1.2  christos static bfd_vma
   5700  1.1.1.2  christos loongarch_get_max_alignment (asection *sec)
   5701  1.1.1.2  christos {
   5702  1.1.1.2  christos   asection *o;
   5703  1.1.1.2  christos   unsigned int max_alignment_power = 0;
   5704  1.1.1.2  christos 
   5705  1.1.1.2  christos   for (o = sec->output_section->owner->sections; o != NULL; o = o->next)
   5706  1.1.1.2  christos       if (o->alignment_power > max_alignment_power)
   5707  1.1.1.2  christos 	max_alignment_power = o->alignment_power;
   5708  1.1.1.2  christos 
   5709  1.1.1.2  christos   return (bfd_vma) 1 << max_alignment_power;
   5710  1.1.1.2  christos }
   5711  1.1.1.2  christos 
   5712  1.1.1.3  christos typedef bool (*relax_func_t) (bfd *, asection *, asection *,
   5713  1.1.1.3  christos 			      Elf_Internal_Rela *, bfd_vma,
   5714  1.1.1.3  christos 			      struct bfd_link_info *, bool *,
   5715  1.1.1.3  christos 			       bfd_vma);
   5716  1.1.1.3  christos 
   5717  1.1.1.2  christos static bool
   5718  1.1.1.2  christos loongarch_elf_relax_section (bfd *abfd, asection *sec,
   5719  1.1.1.3  christos 			     struct bfd_link_info *info,
   5720  1.1.1.3  christos 			     bool *again)
   5721  1.1.1.2  christos {
   5722  1.1.1.2  christos   *again = false;
   5723  1.1.1.2  christos 
   5724  1.1.1.3  christos   if (!is_elf_hash_table (info->hash)
   5725  1.1.1.3  christos       || elf_hash_table_id (elf_hash_table (info)) != LARCH_ELF_DATA)
   5726  1.1.1.3  christos     return true;
   5727  1.1.1.3  christos 
   5728  1.1.1.3  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   5729  1.1.1.3  christos 
   5730  1.1.1.3  christos   /* It may happen that some sections have updated vma but the others do
   5731  1.1.1.3  christos      not.  Go to the next relax trip (size_relative_relocs should have
   5732  1.1.1.3  christos      been demending another relax trip anyway).  */
   5733  1.1.1.3  christos   if (htab->layout_mutating_for_relr)
   5734  1.1.1.3  christos     return true;
   5735  1.1.1.3  christos 
   5736  1.1.1.3  christos   /* Definition of LoongArch linker relaxation passes:
   5737  1.1.1.3  christos 
   5738  1.1.1.3  christos      - Pass 0: relaxes everything except R_LARCH_ALIGN, byte deletions are
   5739  1.1.1.3  christos 	       performed; skipped if disable_target_specific_optimizations.
   5740  1.1.1.3  christos      - Pass 1: handles alignment, byte deletions are performed.  Sections with
   5741  1.1.1.3  christos 	       R_LARCH_ALIGN relocations are marked closed for further byte
   5742  1.1.1.3  christos 	       deletion in order to not disturb alignment.  This pass is NOT
   5743  1.1.1.3  christos 	       skipped even if disable_target_specific_optimizations is true.
   5744  1.1.1.3  christos      - Pass 2: identical to Pass 0, but replacing relaxed insns with NOP in case
   5745  1.1.1.3  christos 	       the containing section is closed for deletion; skip condition
   5746  1.1.1.3  christos 	       also same as Pass 0.  */
   5747  1.1.1.3  christos   bool is_alignment_pass = info->relax_pass == 1;
   5748  1.1.1.2  christos   if (bfd_link_relocatable (info)
   5749  1.1.1.2  christos       || sec->reloc_count == 0
   5750  1.1.1.3  christos       || (sec->flags & SEC_RELOC) == 0
   5751  1.1.1.3  christos       || (sec->flags & SEC_HAS_CONTENTS) == 0
   5752  1.1.1.3  christos       /* The exp_seg_relro_adjust is enum phase_enum (0x4).  */
   5753  1.1.1.3  christos       || *(htab->data_segment_phase) == 4
   5754  1.1.1.3  christos       || (info->disable_target_specific_optimizations && !is_alignment_pass))
   5755  1.1.1.2  christos     return true;
   5756  1.1.1.2  christos 
   5757  1.1.1.3  christos   struct bfd_elf_section_data *data = elf_section_data (sec);
   5758  1.1.1.3  christos   Elf_Internal_Rela *relocs;
   5759  1.1.1.2  christos   if (data->relocs)
   5760  1.1.1.2  christos     relocs = data->relocs;
   5761  1.1.1.2  christos   else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
   5762  1.1.1.2  christos 						 info->keep_memory)))
   5763  1.1.1.2  christos     return true;
   5764  1.1.1.3  christos   data->relocs = relocs;
   5765  1.1.1.2  christos 
   5766  1.1.1.3  christos   /* Read this BFD's contents if we haven't done so already.  */
   5767  1.1.1.2  christos   if (!data->this_hdr.contents
   5768  1.1.1.2  christos       && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents))
   5769  1.1.1.2  christos     return true;
   5770  1.1.1.2  christos 
   5771  1.1.1.3  christos   /* Read this BFD's symbols if we haven't done so already.  */
   5772  1.1.1.3  christos   Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
   5773  1.1.1.2  christos   if (symtab_hdr->sh_info != 0
   5774  1.1.1.2  christos       && !symtab_hdr->contents
   5775  1.1.1.2  christos       && !(symtab_hdr->contents =
   5776  1.1.1.2  christos 	   (unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr,
   5777  1.1.1.2  christos 						   symtab_hdr->sh_info,
   5778  1.1.1.2  christos 						   0, NULL, NULL, NULL)))
   5779  1.1.1.2  christos     return true;
   5780  1.1.1.2  christos 
   5781  1.1.1.2  christos   /* Estimate the maximum alignment for all output sections once time
   5782  1.1.1.2  christos      should be enough.  */
   5783  1.1.1.3  christos   bfd_vma max_alignment = htab->max_alignment;
   5784  1.1.1.2  christos   if (max_alignment == (bfd_vma) -1)
   5785  1.1.1.2  christos     {
   5786  1.1.1.2  christos       max_alignment = loongarch_get_max_alignment (sec);
   5787  1.1.1.2  christos       htab->max_alignment = max_alignment;
   5788  1.1.1.2  christos     }
   5789  1.1.1.2  christos 
   5790  1.1.1.3  christos   splay_tree pdops = NULL;
   5791  1.1.1.3  christos   if (!loongarch_sec_closed_for_deletion (sec))
   5792  1.1.1.3  christos     pdops = pending_delete_ops_new (abfd);
   5793  1.1.1.3  christos 
   5794  1.1.1.3  christos   htab->pending_delete_ops = pdops;
   5795  1.1.1.3  christos 
   5796  1.1.1.2  christos   for (unsigned int i = 0; i < sec->reloc_count; i++)
   5797  1.1.1.2  christos     {
   5798  1.1.1.2  christos       char symtype;
   5799  1.1.1.2  christos       bfd_vma symval;
   5800  1.1.1.2  christos       asection *sym_sec;
   5801  1.1.1.2  christos       bool local_got = false;
   5802  1.1.1.2  christos       Elf_Internal_Rela *rel = relocs + i;
   5803  1.1.1.2  christos       struct elf_link_hash_entry *h = NULL;
   5804  1.1.1.2  christos       unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
   5805  1.1.1.2  christos       unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
   5806  1.1.1.2  christos 
   5807  1.1.1.3  christos       if (r_symndx >= symtab_hdr->sh_info)
   5808  1.1.1.3  christos 	{
   5809  1.1.1.3  christos 	  h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
   5810  1.1.1.3  christos 	  while (h->root.type == bfd_link_hash_indirect
   5811  1.1.1.3  christos 	       || h->root.type == bfd_link_hash_warning)
   5812  1.1.1.3  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
   5813  1.1.1.3  christos 	}
   5814  1.1.1.3  christos 
   5815  1.1.1.3  christos       /* If the conditions for tls type transition are met, type
   5816  1.1.1.3  christos 	 transition is performed instead of relax.
   5817  1.1.1.3  christos 	 During the transition from DESC->IE/LE, there are 2 situations
   5818  1.1.1.3  christos 	 depending on the different configurations of the relax/norelax
   5819  1.1.1.3  christos 	 option.
   5820  1.1.1.3  christos 	 If the -relax option is used, the extra nops will be removed,
   5821  1.1.1.3  christos 	 and this transition is performed in pass 0.
   5822  1.1.1.3  christos 	 If the --no-relax option is used, nop will be retained, and
   5823  1.1.1.3  christos 	 this transition is performed in pass 1.  */
   5824  1.1.1.3  christos       if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type)
   5825  1.1.1.3  christos 	  && (i + 1 != sec->reloc_count)
   5826  1.1.1.3  christos 	  && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
   5827  1.1.1.3  christos 	  && rel->r_offset == rel[1].r_offset
   5828  1.1.1.3  christos 	  && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type))
   5829  1.1.1.3  christos 	{
   5830  1.1.1.3  christos 	  loongarch_tls_perform_trans (abfd, sec, rel, h, info);
   5831  1.1.1.3  christos 	  r_type = ELFNN_R_TYPE (rel->r_info);
   5832  1.1.1.3  christos 	}
   5833  1.1.1.3  christos 
   5834  1.1.1.3  christos       relax_func_t relax_func = NULL;
   5835  1.1.1.3  christos       if (is_alignment_pass)
   5836  1.1.1.3  christos 	{
   5837  1.1.1.3  christos 	  if (r_type != R_LARCH_ALIGN)
   5838  1.1.1.3  christos 	    continue;
   5839  1.1.1.3  christos 	  relax_func = loongarch_relax_align;
   5840  1.1.1.3  christos 	}
   5841  1.1.1.3  christos       else
   5842  1.1.1.3  christos 	{
   5843  1.1.1.3  christos 	  switch (r_type)
   5844  1.1.1.3  christos 	    {
   5845  1.1.1.3  christos 	    case R_LARCH_PCALA_HI20:
   5846  1.1.1.3  christos 	      relax_func = loongarch_relax_pcala_addi;
   5847  1.1.1.3  christos 	      break;
   5848  1.1.1.3  christos 	    case R_LARCH_GOT_PC_HI20:
   5849  1.1.1.3  christos 	      relax_func = loongarch_relax_pcala_ld;
   5850  1.1.1.3  christos 	      break;
   5851  1.1.1.3  christos 	    case R_LARCH_CALL36:
   5852  1.1.1.3  christos 	      relax_func = loongarch_relax_call36;
   5853  1.1.1.3  christos 	      break;
   5854  1.1.1.3  christos 	    case R_LARCH_TLS_LE_HI20_R:
   5855  1.1.1.3  christos 	    case R_LARCH_TLS_LE_LO12_R:
   5856  1.1.1.3  christos 	    case R_LARCH_TLS_LE_ADD_R:
   5857  1.1.1.3  christos 	    case R_LARCH_TLS_LE_HI20:
   5858  1.1.1.3  christos 	    case R_LARCH_TLS_LE_LO12:
   5859  1.1.1.3  christos 	    case R_LARCH_TLS_LE64_LO20:
   5860  1.1.1.3  christos 	    case R_LARCH_TLS_LE64_HI12:
   5861  1.1.1.3  christos 	      relax_func = loongarch_relax_tls_le;
   5862  1.1.1.3  christos 	      break;
   5863  1.1.1.3  christos 	    case R_LARCH_TLS_LD_PC_HI20:
   5864  1.1.1.3  christos 	    case R_LARCH_TLS_GD_PC_HI20:
   5865  1.1.1.3  christos 	    case R_LARCH_TLS_DESC_PC_HI20:
   5866  1.1.1.3  christos 	      relax_func = loongarch_relax_tls_ld_gd_desc;
   5867  1.1.1.3  christos 	      break;
   5868  1.1.1.3  christos 	    default:
   5869  1.1.1.3  christos 		continue;
   5870  1.1.1.3  christos 	    }
   5871  1.1.1.3  christos 
   5872  1.1.1.3  christos 	  /* Only relax this reloc if it is paired with R_RISCV_RELAX.  */
   5873  1.1.1.3  christos 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
   5874  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_GD_PC_HI20
   5875  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_DESC_PC_HI20
   5876  1.1.1.3  christos 	      || r_type == R_LARCH_PCALA_HI20
   5877  1.1.1.3  christos 	      || r_type == R_LARCH_GOT_PC_HI20)
   5878  1.1.1.3  christos 	    {
   5879  1.1.1.3  christos 	      if ((i + 2) == sec->reloc_count - 1
   5880  1.1.1.3  christos 		  || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX
   5881  1.1.1.3  christos 		  || ELFNN_R_TYPE ((rel + 3)->r_info) != R_LARCH_RELAX
   5882  1.1.1.3  christos 		  || rel->r_offset != (rel + 1)->r_offset
   5883  1.1.1.3  christos 		  || (rel + 2)->r_offset != (rel + 3)->r_offset
   5884  1.1.1.3  christos 		  || rel->r_offset + 4 != (rel + 2)->r_offset)
   5885  1.1.1.3  christos 		continue;
   5886  1.1.1.3  christos 	    }
   5887  1.1.1.3  christos 	  else
   5888  1.1.1.3  christos 	    {
   5889  1.1.1.3  christos 	      if (i == sec->reloc_count - 1
   5890  1.1.1.3  christos 		  || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX
   5891  1.1.1.3  christos 		  || rel->r_offset != (rel + 1)->r_offset)
   5892  1.1.1.3  christos 		continue;
   5893  1.1.1.3  christos 	    }
   5894  1.1.1.3  christos 	}
   5895  1.1.1.3  christos 
   5896  1.1.1.2  christos       /* Four kind of relocations:
   5897  1.1.1.2  christos 	 Normal: symval is the symbol address.
   5898  1.1.1.2  christos 	 R_LARCH_ALIGN: symval is the address of the last NOP instruction
   5899  1.1.1.2  christos 	 added by this relocation, and then adds 4 more.
   5900  1.1.1.2  christos 	 R_LARCH_CALL36: symval is the symbol address for local symbols,
   5901  1.1.1.2  christos 	 or the PLT entry address of the symbol. (Todo)
   5902  1.1.1.2  christos 	 R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
   5903  1.1.1.3  christos 	 of the symbol if transition is not possible.  */
   5904  1.1.1.2  christos       if (r_symndx < symtab_hdr->sh_info)
   5905  1.1.1.2  christos 	{
   5906  1.1.1.2  christos 	  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
   5907  1.1.1.2  christos 				    + r_symndx;
   5908  1.1.1.3  christos 
   5909  1.1.1.3  christos 	  if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
   5910  1.1.1.3  christos 	       && r_type != R_LARCH_CALL36)
   5911  1.1.1.3  christos 	      || sym->st_shndx == SHN_ABS)
   5912  1.1.1.2  christos 	    continue;
   5913  1.1.1.2  christos 
   5914  1.1.1.3  christos 	  /* Only TLS instruction sequences that are accompanied by
   5915  1.1.1.3  christos 	     R_LARCH_RELAX and cannot perform type transition can be
   5916  1.1.1.3  christos 	     relaxed.  */
   5917  1.1.1.3  christos 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
   5918  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_GD_PC_HI20
   5919  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
   5920  1.1.1.2  christos 	    {
   5921  1.1.1.3  christos 	      sym_sec = htab->elf.sgot;
   5922  1.1.1.3  christos 	      symval = elf_local_got_offsets (abfd)[r_symndx];
   5923  1.1.1.3  christos 	      char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
   5924  1.1.1.3  christos 							    r_symndx);
   5925  1.1.1.3  christos 	      if (r_type == R_LARCH_TLS_DESC_PC_HI20
   5926  1.1.1.3  christos 		    && GOT_TLS_GD_BOTH_P (tls_type))
   5927  1.1.1.3  christos 		symval += 2 * GOT_ENTRY_SIZE;
   5928  1.1.1.2  christos 	    }
   5929  1.1.1.3  christos 	  else if (sym->st_shndx == SHN_UNDEF || r_type == R_LARCH_ALIGN)
   5930  1.1.1.2  christos 	    {
   5931  1.1.1.2  christos 	      sym_sec = sec;
   5932  1.1.1.2  christos 	      symval = rel->r_offset;
   5933  1.1.1.2  christos 	    }
   5934  1.1.1.2  christos 	  else
   5935  1.1.1.2  christos 	    {
   5936  1.1.1.2  christos 	      sym_sec = elf_elfsections (abfd)[sym->st_shndx]->bfd_section;
   5937  1.1.1.2  christos 	      symval = sym->st_value;
   5938  1.1.1.2  christos 	    }
   5939  1.1.1.2  christos 	  symtype = ELF_ST_TYPE (sym->st_info);
   5940  1.1.1.2  christos 	}
   5941  1.1.1.2  christos       else
   5942  1.1.1.2  christos 	{
   5943  1.1.1.3  christos 	  /* Do not relax __[start|stop]_SECNAME, since the symbol value
   5944  1.1.1.3  christos 	     is not set yet.  */
   5945  1.1.1.3  christos 	  if (h != NULL
   5946  1.1.1.3  christos 	      && ((h->type == STT_GNU_IFUNC
   5947  1.1.1.3  christos 		   && r_type != R_LARCH_CALL36)
   5948  1.1.1.3  christos 		  || bfd_is_abs_section (h->root.u.def.section)
   5949  1.1.1.3  christos 		  || h->start_stop))
   5950  1.1.1.2  christos 	    continue;
   5951  1.1.1.2  christos 
   5952  1.1.1.2  christos 	  /* The GOT entry of tls symbols must in current execute file or
   5953  1.1.1.2  christos 	     shared object.  */
   5954  1.1.1.3  christos 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
   5955  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_GD_PC_HI20
   5956  1.1.1.3  christos 	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
   5957  1.1.1.2  christos 	    {
   5958  1.1.1.3  christos 	      sym_sec = htab->elf.sgot;
   5959  1.1.1.3  christos 	      symval = h->got.offset;
   5960  1.1.1.3  christos 	      char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
   5961  1.1.1.3  christos 							    r_symndx);
   5962  1.1.1.3  christos 	      if (r_type == R_LARCH_TLS_DESC_PC_HI20
   5963  1.1.1.3  christos 		    && GOT_TLS_GD_BOTH_P (tls_type))
   5964  1.1.1.3  christos 		symval += 2 * GOT_ENTRY_SIZE;
   5965  1.1.1.3  christos 	    }
   5966  1.1.1.3  christos 	  else if (h->plt.offset != MINUS_ONE)
   5967  1.1.1.3  christos 	    {
   5968  1.1.1.3  christos 	      sym_sec = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
   5969  1.1.1.3  christos 	      symval = h->plt.offset;
   5970  1.1.1.3  christos 	    }
   5971  1.1.1.3  christos 	  /* Like loongarch_elf_relocate_section, set relocation(offset) to 0.
   5972  1.1.1.3  christos 	     Undefweak for other relocations handing in the future.  */
   5973  1.1.1.3  christos 	  else if (h->root.type == bfd_link_hash_undefweak
   5974  1.1.1.3  christos 		    && !h->root.linker_def
   5975  1.1.1.3  christos 		    && r_type == R_LARCH_CALL36)
   5976  1.1.1.3  christos 	    {
   5977  1.1.1.3  christos 	      sym_sec = sec;
   5978  1.1.1.3  christos 	      symval = rel->r_offset;
   5979  1.1.1.2  christos 	    }
   5980  1.1.1.2  christos 	  else if ((h->root.type == bfd_link_hash_defined
   5981  1.1.1.2  christos 		  || h->root.type == bfd_link_hash_defweak)
   5982  1.1.1.2  christos 		&& h->root.u.def.section != NULL
   5983  1.1.1.2  christos 		&& h->root.u.def.section->output_section != NULL)
   5984  1.1.1.2  christos 	    {
   5985  1.1.1.2  christos 	      sym_sec = h->root.u.def.section;
   5986  1.1.1.3  christos 	      symval = h->root.u.def.value;
   5987  1.1.1.2  christos 	    }
   5988  1.1.1.2  christos 	  else
   5989  1.1.1.2  christos 	    continue;
   5990  1.1.1.2  christos 
   5991  1.1.1.3  christos 	  if (h && LARCH_REF_LOCAL (info, h))
   5992  1.1.1.2  christos 	    local_got = true;
   5993  1.1.1.2  christos 	  symtype = h->type;
   5994  1.1.1.2  christos 	}
   5995  1.1.1.2  christos 
   5996  1.1.1.2  christos       if (sym_sec->sec_info_type == SEC_INFO_TYPE_MERGE
   5997  1.1.1.2  christos 	   && (sym_sec->flags & SEC_MERGE))
   5998  1.1.1.2  christos 	{
   5999  1.1.1.2  christos 	   if (symtype == STT_SECTION)
   6000  1.1.1.2  christos 	     symval += rel->r_addend;
   6001  1.1.1.2  christos 
   6002  1.1.1.2  christos 	   symval = _bfd_merged_section_offset (abfd, &sym_sec,
   6003  1.1.1.2  christos 				elf_section_data (sym_sec)->sec_info,
   6004  1.1.1.2  christos 				symval);
   6005  1.1.1.2  christos 
   6006  1.1.1.2  christos 	   if (symtype != STT_SECTION)
   6007  1.1.1.2  christos 	     symval += rel->r_addend;
   6008  1.1.1.2  christos 	}
   6009  1.1.1.2  christos       /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
   6010  1.1.1.2  christos 	 + (alingmeng - 4).
   6011  1.1.1.2  christos 	 If r_symndx is 0, alignmeng-4 is r_addend.
   6012  1.1.1.2  christos 	 If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
   6013  1.1.1.3  christos       else if (r_type == R_LARCH_ALIGN)
   6014  1.1.1.2  christos 	if (r_symndx > 0)
   6015  1.1.1.2  christos 	  symval += ((1 << (rel->r_addend & 0xff)) - 4);
   6016  1.1.1.2  christos 	else
   6017  1.1.1.2  christos 	  symval += rel->r_addend;
   6018  1.1.1.2  christos       else
   6019  1.1.1.2  christos 	symval += rel->r_addend;
   6020  1.1.1.2  christos 
   6021  1.1.1.2  christos       symval += sec_addr (sym_sec);
   6022  1.1.1.2  christos 
   6023  1.1.1.3  christos       if (r_type == R_LARCH_GOT_PC_HI20 && !local_got)
   6024  1.1.1.3  christos 	continue;
   6025  1.1.1.2  christos 
   6026  1.1.1.3  christos       if (relax_func (abfd, sec, sym_sec, rel, symval,
   6027  1.1.1.3  christos 		      info, again, max_alignment)
   6028  1.1.1.3  christos 	  && relax_func == loongarch_relax_pcala_ld)
   6029  1.1.1.3  christos 	loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
   6030  1.1.1.3  christos 				    info, again, max_alignment);
   6031  1.1.1.3  christos     }
   6032  1.1.1.2  christos 
   6033  1.1.1.3  christos   if (pdops)
   6034  1.1.1.3  christos     {
   6035  1.1.1.3  christos       loongarch_relax_perform_deletes (abfd, sec, info);
   6036  1.1.1.3  christos       htab->pending_delete_ops = NULL;
   6037  1.1.1.3  christos       splay_tree_delete (pdops);
   6038  1.1.1.2  christos     }
   6039  1.1.1.2  christos 
   6040  1.1.1.2  christos   return true;
   6041  1.1.1.2  christos }
   6042  1.1.1.2  christos 
   6043      1.1  christos /* Finish up dynamic symbol handling.  We set the contents of various
   6044      1.1  christos    dynamic sections here.  */
   6045      1.1  christos 
   6046      1.1  christos static bool
   6047      1.1  christos loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
   6048      1.1  christos 				     struct bfd_link_info *info,
   6049      1.1  christos 				     struct elf_link_hash_entry *h,
   6050      1.1  christos 				     Elf_Internal_Sym *sym)
   6051      1.1  christos {
   6052      1.1  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   6053      1.1  christos   const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
   6054      1.1  christos 
   6055      1.1  christos   if (h->plt.offset != MINUS_ONE)
   6056      1.1  christos     {
   6057      1.1  christos       size_t i, plt_idx;
   6058      1.1  christos       asection *plt, *gotplt, *relplt;
   6059      1.1  christos       bfd_vma got_address;
   6060      1.1  christos       uint32_t plt_entry[PLT_ENTRY_INSNS];
   6061      1.1  christos       bfd_byte *loc;
   6062      1.1  christos       Elf_Internal_Rela rela;
   6063      1.1  christos 
   6064      1.1  christos       if (htab->elf.splt)
   6065      1.1  christos 	{
   6066      1.1  christos 	  BFD_ASSERT ((h->type == STT_GNU_IFUNC
   6067  1.1.1.3  christos 		       && LARCH_REF_LOCAL (info, h))
   6068      1.1  christos 		      || h->dynindx != -1);
   6069      1.1  christos 
   6070      1.1  christos 	  plt = htab->elf.splt;
   6071      1.1  christos 	  gotplt = htab->elf.sgotplt;
   6072  1.1.1.3  christos 	  if (h->type == STT_GNU_IFUNC && LARCH_REF_LOCAL (info, h))
   6073  1.1.1.2  christos 	    relplt = htab->elf.srelgot;
   6074  1.1.1.2  christos 	  else
   6075  1.1.1.2  christos 	    relplt = htab->elf.srelplt;
   6076      1.1  christos 	  plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
   6077      1.1  christos 	  got_address =
   6078      1.1  christos 	    sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
   6079      1.1  christos 	}
   6080      1.1  christos       else /* if (htab->elf.iplt) */
   6081      1.1  christos 	{
   6082      1.1  christos 	  BFD_ASSERT (h->type == STT_GNU_IFUNC
   6083  1.1.1.3  christos 		      && LARCH_REF_LOCAL (info, h));
   6084      1.1  christos 
   6085      1.1  christos 	  plt = htab->elf.iplt;
   6086      1.1  christos 	  gotplt = htab->elf.igotplt;
   6087      1.1  christos 	  relplt = htab->elf.irelplt;
   6088      1.1  christos 	  plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
   6089      1.1  christos 	  got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
   6090      1.1  christos 	}
   6091      1.1  christos 
   6092      1.1  christos       /* Find out where the .plt entry should go.  */
   6093      1.1  christos       loc = plt->contents + h->plt.offset;
   6094      1.1  christos 
   6095      1.1  christos       /* Fill in the PLT entry itself.  */
   6096      1.1  christos       if (!loongarch_make_plt_entry (got_address,
   6097      1.1  christos 				     sec_addr (plt) + h->plt.offset,
   6098      1.1  christos 				     plt_entry))
   6099      1.1  christos 	return false;
   6100      1.1  christos 
   6101      1.1  christos       for (i = 0; i < PLT_ENTRY_INSNS; i++)
   6102      1.1  christos 	bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
   6103      1.1  christos 
   6104  1.1.1.2  christos       /* Fill in the initial value of the got.plt entry.  */
   6105      1.1  christos       loc = gotplt->contents + (got_address - sec_addr (gotplt));
   6106      1.1  christos       bfd_put_NN (output_bfd, sec_addr (plt), loc);
   6107      1.1  christos 
   6108      1.1  christos       rela.r_offset = got_address;
   6109      1.1  christos 
   6110      1.1  christos       /* TRUE if this is a PLT reference to a local IFUNC.  */
   6111  1.1.1.2  christos       if (PLT_LOCAL_IFUNC_P (info, h)
   6112  1.1.1.2  christos 	  && (relplt == htab->elf.srelgot
   6113  1.1.1.2  christos 	      || relplt == htab->elf.irelplt))
   6114      1.1  christos 	{
   6115      1.1  christos 	  rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
   6116      1.1  christos 	  rela.r_addend = (h->root.u.def.value
   6117  1.1.1.2  christos 			       + h->root.u.def.section->output_section->vma
   6118  1.1.1.2  christos 			       + h->root.u.def.section->output_offset);
   6119  1.1.1.2  christos 
   6120  1.1.1.2  christos 	  loongarch_elf_append_rela (output_bfd, relplt, &rela);
   6121      1.1  christos 	}
   6122      1.1  christos       else
   6123      1.1  christos 	{
   6124  1.1.1.2  christos 	  /* Fill in the entry in the rela.plt section.  */
   6125      1.1  christos 	  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
   6126      1.1  christos 	  rela.r_addend = 0;
   6127  1.1.1.2  christos 	  loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
   6128  1.1.1.2  christos 	  bed->s->swap_reloca_out (output_bfd, &rela, loc);
   6129      1.1  christos 	}
   6130      1.1  christos 
   6131      1.1  christos       if (!h->def_regular)
   6132      1.1  christos 	{
   6133      1.1  christos 	  /* Mark the symbol as undefined, rather than as defined in
   6134      1.1  christos 	     the .plt section.  Leave the value alone.  */
   6135      1.1  christos 	  sym->st_shndx = SHN_UNDEF;
   6136      1.1  christos 	  /* If the symbol is weak, we do need to clear the value.
   6137      1.1  christos 	     Otherwise, the PLT entry would provide a definition for
   6138      1.1  christos 	     the symbol even if the symbol wasn't defined anywhere,
   6139      1.1  christos 	     and so the symbol would never be NULL.  */
   6140      1.1  christos 	  if (!h->ref_regular_nonweak)
   6141      1.1  christos 	    sym->st_value = 0;
   6142      1.1  christos 	}
   6143      1.1  christos     }
   6144      1.1  christos 
   6145      1.1  christos   if (h->got.offset != MINUS_ONE
   6146      1.1  christos       /* TLS got entry have been handled in elf_relocate_section.  */
   6147  1.1.1.2  christos       && !(loongarch_elf_hash_entry (h)->tls_type
   6148  1.1.1.2  christos 	   & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
   6149  1.1.1.2  christos       /* Have allocated got entry but not allocated rela before.  */
   6150      1.1  christos       && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
   6151      1.1  christos     {
   6152      1.1  christos       asection *sgot, *srela;
   6153      1.1  christos       Elf_Internal_Rela rela;
   6154  1.1.1.2  christos       bfd_vma off = h->got.offset & ~(bfd_vma)1;
   6155      1.1  christos 
   6156      1.1  christos       /* This symbol has an entry in the GOT.  Set it up.  */
   6157      1.1  christos       sgot = htab->elf.sgot;
   6158      1.1  christos       srela = htab->elf.srelgot;
   6159      1.1  christos       BFD_ASSERT (sgot && srela);
   6160      1.1  christos 
   6161      1.1  christos       rela.r_offset = sec_addr (sgot) + off;
   6162      1.1  christos 
   6163      1.1  christos       if (h->def_regular
   6164      1.1  christos 	  && h->type == STT_GNU_IFUNC)
   6165      1.1  christos 	{
   6166      1.1  christos 	  if(h->plt.offset == MINUS_ONE)
   6167      1.1  christos 	    {
   6168      1.1  christos 	      if (htab->elf.splt == NULL)
   6169      1.1  christos 		srela = htab->elf.irelplt;
   6170      1.1  christos 
   6171  1.1.1.3  christos 	      if (LARCH_REF_LOCAL (info, h))
   6172      1.1  christos 		{
   6173      1.1  christos 		  asection *sec = h->root.u.def.section;
   6174      1.1  christos 		  rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
   6175      1.1  christos 		  rela.r_addend = h->root.u.def.value + sec->output_section->vma
   6176      1.1  christos 		    + sec->output_offset;
   6177      1.1  christos 		  bfd_put_NN (output_bfd, 0, sgot->contents + off);
   6178      1.1  christos 		}
   6179      1.1  christos 	      else
   6180      1.1  christos 		{
   6181      1.1  christos 		  BFD_ASSERT (h->dynindx != -1);
   6182      1.1  christos 		  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
   6183      1.1  christos 		  rela.r_addend = 0;
   6184      1.1  christos 		  bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off);
   6185      1.1  christos 		}
   6186      1.1  christos 	    }
   6187      1.1  christos 	  else if(bfd_link_pic (info))
   6188      1.1  christos 	    {
   6189      1.1  christos 	      rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
   6190      1.1  christos 	      rela.r_addend = 0;
   6191      1.1  christos 	      bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
   6192      1.1  christos 	    }
   6193      1.1  christos 	  else
   6194      1.1  christos 	    {
   6195      1.1  christos 	      asection *plt;
   6196      1.1  christos 	      /* For non-shared object, we can't use .got.plt, which
   6197      1.1  christos 		 contains the real function address if we need pointer
   6198      1.1  christos 		 equality.  We load the GOT entry with the PLT entry.  */
   6199      1.1  christos 	      plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
   6200      1.1  christos 	      bfd_put_NN (output_bfd,
   6201      1.1  christos 			  (plt->output_section->vma
   6202      1.1  christos 			   + plt->output_offset
   6203      1.1  christos 			   + h->plt.offset),
   6204      1.1  christos 			  sgot->contents + off);
   6205      1.1  christos 	      return true;
   6206      1.1  christos 	    }
   6207      1.1  christos 	}
   6208  1.1.1.3  christos       else if (bfd_link_pic (info) && LARCH_REF_LOCAL (info, h))
   6209      1.1  christos 	{
   6210      1.1  christos 	  asection *sec = h->root.u.def.section;
   6211  1.1.1.3  christos 	  bfd_vma linkaddr = h->root.u.def.value + sec->output_section->vma
   6212  1.1.1.3  christos 			     + sec->output_offset;
   6213  1.1.1.3  christos 
   6214  1.1.1.3  christos 	  /* Don't emit relative relocs if they are packed, but we need
   6215  1.1.1.3  christos 	     to write the addend (link-time addr) into the GOT then.  */
   6216  1.1.1.3  christos 	  if (info->enable_dt_relr)
   6217  1.1.1.3  christos 	    {
   6218  1.1.1.3  christos 	      bfd_put_NN (output_bfd, linkaddr, sgot->contents + off);
   6219  1.1.1.3  christos 	      goto skip_got_reloc;
   6220  1.1.1.3  christos 	    }
   6221      1.1  christos 	  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
   6222  1.1.1.3  christos 	  rela.r_addend = linkaddr;
   6223      1.1  christos 	}
   6224      1.1  christos       else
   6225      1.1  christos 	{
   6226      1.1  christos 	  BFD_ASSERT (h->dynindx != -1);
   6227      1.1  christos 	  rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
   6228      1.1  christos 	  rela.r_addend = 0;
   6229      1.1  christos 	}
   6230      1.1  christos 
   6231      1.1  christos       loongarch_elf_append_rela (output_bfd, srela, &rela);
   6232      1.1  christos     }
   6233  1.1.1.3  christos skip_got_reloc:
   6234      1.1  christos 
   6235      1.1  christos   /* Mark some specially defined symbols as absolute.  */
   6236      1.1  christos   if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
   6237      1.1  christos     sym->st_shndx = SHN_ABS;
   6238      1.1  christos 
   6239      1.1  christos   return true;
   6240      1.1  christos }
   6241      1.1  christos 
   6242      1.1  christos /* Finish up the dynamic sections.  */
   6243      1.1  christos 
   6244      1.1  christos static bool
   6245      1.1  christos loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
   6246      1.1  christos 		      asection *sdyn)
   6247      1.1  christos {
   6248      1.1  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   6249      1.1  christos   const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
   6250      1.1  christos   size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
   6251      1.1  christos   bfd_byte *dyncon, *dynconend;
   6252      1.1  christos 
   6253      1.1  christos   dynconend = sdyn->contents + sdyn->size;
   6254      1.1  christos   for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
   6255      1.1  christos     {
   6256      1.1  christos       Elf_Internal_Dyn dyn;
   6257      1.1  christos       asection *s;
   6258      1.1  christos       int skipped = 0;
   6259      1.1  christos 
   6260      1.1  christos       bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
   6261      1.1  christos 
   6262      1.1  christos       switch (dyn.d_tag)
   6263      1.1  christos 	{
   6264      1.1  christos 	case DT_PLTGOT:
   6265      1.1  christos 	  s = htab->elf.sgotplt;
   6266      1.1  christos 	  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
   6267      1.1  christos 	  break;
   6268      1.1  christos 	case DT_JMPREL:
   6269      1.1  christos 	  s = htab->elf.srelplt;
   6270      1.1  christos 	  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
   6271      1.1  christos 	  break;
   6272      1.1  christos 	case DT_PLTRELSZ:
   6273      1.1  christos 	  s = htab->elf.srelplt;
   6274      1.1  christos 	  dyn.d_un.d_val = s->size;
   6275      1.1  christos 	  break;
   6276      1.1  christos 	case DT_TEXTREL:
   6277      1.1  christos 	  if ((info->flags & DF_TEXTREL) == 0)
   6278      1.1  christos 	    skipped = 1;
   6279      1.1  christos 	  break;
   6280      1.1  christos 	case DT_FLAGS:
   6281      1.1  christos 	  if ((info->flags & DF_TEXTREL) == 0)
   6282      1.1  christos 	    dyn.d_un.d_val &= ~DF_TEXTREL;
   6283      1.1  christos 	  break;
   6284      1.1  christos 	}
   6285      1.1  christos       if (skipped)
   6286      1.1  christos 	skipped_size += dynsize;
   6287      1.1  christos       else
   6288      1.1  christos 	bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
   6289      1.1  christos     }
   6290      1.1  christos   /* Wipe out any trailing entries if we shifted down a dynamic tag.  */
   6291      1.1  christos   memset (dyncon - skipped_size, 0, skipped_size);
   6292      1.1  christos   return true;
   6293      1.1  christos }
   6294      1.1  christos 
   6295      1.1  christos /* Finish up local dynamic symbol handling.  We set the contents of
   6296      1.1  christos    various dynamic sections here.  */
   6297      1.1  christos 
   6298  1.1.1.2  christos static int
   6299      1.1  christos elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
   6300      1.1  christos {
   6301      1.1  christos   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
   6302      1.1  christos   struct bfd_link_info *info = (struct bfd_link_info *) inf;
   6303      1.1  christos 
   6304      1.1  christos   return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
   6305      1.1  christos }
   6306      1.1  christos 
   6307  1.1.1.2  christos /* Value of struct elf_backend_data->elf_backend_output_arch_local_syms,
   6308  1.1.1.2  christos    this function is called before elf_link_sort_relocs.
   6309  1.1.1.2  christos    So relocation R_LARCH_IRELATIVE for local ifunc can be append to
   6310  1.1.1.2  christos    .rela.dyn (.rela.got) by loongarch_elf_append_rela.  */
   6311  1.1.1.2  christos 
   6312  1.1.1.2  christos static bool
   6313  1.1.1.2  christos elf_loongarch_output_arch_local_syms
   6314  1.1.1.2  christos   (bfd *output_bfd ATTRIBUTE_UNUSED,
   6315  1.1.1.2  christos    struct bfd_link_info *info,
   6316  1.1.1.2  christos    void *flaginfo ATTRIBUTE_UNUSED,
   6317  1.1.1.2  christos    int (*func) (void *, const char *,
   6318  1.1.1.2  christos 		Elf_Internal_Sym *,
   6319  1.1.1.2  christos 		asection *,
   6320  1.1.1.2  christos 		struct elf_link_hash_entry *) ATTRIBUTE_UNUSED)
   6321  1.1.1.2  christos {
   6322  1.1.1.2  christos   struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
   6323  1.1.1.2  christos   if (htab == NULL)
   6324  1.1.1.2  christos     return false;
   6325  1.1.1.2  christos 
   6326  1.1.1.2  christos   /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
   6327  1.1.1.2  christos   htab_traverse (htab->loc_hash_table,
   6328  1.1.1.2  christos 		 elfNN_loongarch_finish_local_dynamic_symbol,
   6329  1.1.1.2  christos 		 info);
   6330  1.1.1.2  christos 
   6331  1.1.1.2  christos   return true;
   6332  1.1.1.2  christos }
   6333  1.1.1.2  christos 
   6334      1.1  christos static bool
   6335      1.1  christos loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
   6336      1.1  christos 				       struct bfd_link_info *info)
   6337      1.1  christos {
   6338      1.1  christos   bfd *dynobj;
   6339      1.1  christos   asection *sdyn, *plt, *gotplt = NULL;
   6340      1.1  christos   struct loongarch_elf_link_hash_table *htab;
   6341      1.1  christos 
   6342      1.1  christos   htab = loongarch_elf_hash_table (info);
   6343      1.1  christos   BFD_ASSERT (htab);
   6344      1.1  christos   dynobj = htab->elf.dynobj;
   6345      1.1  christos   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   6346      1.1  christos 
   6347      1.1  christos   if (elf_hash_table (info)->dynamic_sections_created)
   6348      1.1  christos     {
   6349      1.1  christos       BFD_ASSERT (htab->elf.splt && sdyn);
   6350      1.1  christos 
   6351      1.1  christos       if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
   6352      1.1  christos 	return false;
   6353      1.1  christos     }
   6354      1.1  christos 
   6355      1.1  christos   plt = htab->elf.splt;
   6356      1.1  christos   gotplt = htab->elf.sgotplt;
   6357      1.1  christos 
   6358      1.1  christos   if (plt && 0 < plt->size)
   6359      1.1  christos     {
   6360      1.1  christos       size_t i;
   6361      1.1  christos       uint32_t plt_header[PLT_HEADER_INSNS];
   6362      1.1  christos       if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
   6363      1.1  christos 				      plt_header))
   6364      1.1  christos 	return false;
   6365      1.1  christos 
   6366      1.1  christos       for (i = 0; i < PLT_HEADER_INSNS; i++)
   6367      1.1  christos 	bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
   6368      1.1  christos 
   6369      1.1  christos       elf_section_data (plt->output_section)->this_hdr.sh_entsize =
   6370      1.1  christos 	PLT_ENTRY_SIZE;
   6371      1.1  christos     }
   6372      1.1  christos 
   6373      1.1  christos   if (htab->elf.sgotplt)
   6374      1.1  christos     {
   6375      1.1  christos       asection *output_section = htab->elf.sgotplt->output_section;
   6376      1.1  christos 
   6377      1.1  christos       if (bfd_is_abs_section (output_section))
   6378      1.1  christos 	{
   6379      1.1  christos 	  _bfd_error_handler (_("discarded output section: `%pA'"),
   6380      1.1  christos 			      htab->elf.sgotplt);
   6381      1.1  christos 	  return false;
   6382      1.1  christos 	}
   6383      1.1  christos 
   6384      1.1  christos       if (0 < htab->elf.sgotplt->size)
   6385      1.1  christos 	{
   6386      1.1  christos 	  /* Write the first two entries in .got.plt, needed for the dynamic
   6387      1.1  christos 	     linker.  */
   6388      1.1  christos 	  bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
   6389      1.1  christos 
   6390      1.1  christos 	  bfd_put_NN (output_bfd, (bfd_vma) 0,
   6391      1.1  christos 		      htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
   6392      1.1  christos 	}
   6393      1.1  christos 
   6394      1.1  christos       elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
   6395      1.1  christos     }
   6396      1.1  christos 
   6397      1.1  christos   if (htab->elf.sgot)
   6398      1.1  christos     {
   6399      1.1  christos       asection *output_section = htab->elf.sgot->output_section;
   6400      1.1  christos 
   6401      1.1  christos       if (0 < htab->elf.sgot->size)
   6402      1.1  christos 	{
   6403      1.1  christos 	  /* Set the first entry in the global offset table to the address of
   6404      1.1  christos 	     the dynamic section.  */
   6405      1.1  christos 	  bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
   6406      1.1  christos 	  bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
   6407      1.1  christos 	}
   6408      1.1  christos 
   6409      1.1  christos       elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
   6410      1.1  christos     }
   6411      1.1  christos 
   6412      1.1  christos   return true;
   6413      1.1  christos }
   6414      1.1  christos 
   6415      1.1  christos /* Return address for Ith PLT stub in section PLT, for relocation REL
   6416      1.1  christos    or (bfd_vma) -1 if it should not be included.  */
   6417      1.1  christos 
   6418      1.1  christos static bfd_vma
   6419      1.1  christos loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
   6420      1.1  christos 			   const arelent *rel ATTRIBUTE_UNUSED)
   6421      1.1  christos {
   6422      1.1  christos   return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
   6423      1.1  christos }
   6424      1.1  christos 
   6425      1.1  christos static enum elf_reloc_type_class
   6426      1.1  christos loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
   6427      1.1  christos 			    const asection *rel_sec ATTRIBUTE_UNUSED,
   6428      1.1  christos 			    const Elf_Internal_Rela *rela)
   6429      1.1  christos {
   6430      1.1  christos   struct loongarch_elf_link_hash_table *htab;
   6431      1.1  christos   htab = loongarch_elf_hash_table (info);
   6432      1.1  christos 
   6433      1.1  christos   if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
   6434      1.1  christos     {
   6435      1.1  christos       /* Check relocation against STT_GNU_IFUNC symbol if there are
   6436      1.1  christos 	 dynamic symbols.  */
   6437      1.1  christos       bfd *abfd = info->output_bfd;
   6438      1.1  christos       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   6439      1.1  christos       unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
   6440      1.1  christos       if (r_symndx != STN_UNDEF)
   6441      1.1  christos 	{
   6442      1.1  christos 	  Elf_Internal_Sym sym;
   6443      1.1  christos 	  if (!bed->s->swap_symbol_in (abfd,
   6444      1.1  christos 				       htab->elf.dynsym->contents
   6445      1.1  christos 				       + r_symndx * bed->s->sizeof_sym,
   6446      1.1  christos 				       0, &sym))
   6447      1.1  christos 	    {
   6448      1.1  christos 	      /* xgettext:c-format  */
   6449      1.1  christos 	      _bfd_error_handler (_("%pB symbol number %lu references"
   6450      1.1  christos 				    " nonexistent SHT_SYMTAB_SHNDX section"),
   6451      1.1  christos 				  abfd, r_symndx);
   6452      1.1  christos 	      /* Ideally an error class should be returned here.  */
   6453      1.1  christos 	    }
   6454      1.1  christos 	  else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
   6455      1.1  christos 	    return reloc_class_ifunc;
   6456      1.1  christos 	}
   6457      1.1  christos     }
   6458      1.1  christos 
   6459      1.1  christos   switch (ELFNN_R_TYPE (rela->r_info))
   6460      1.1  christos     {
   6461      1.1  christos     case R_LARCH_IRELATIVE:
   6462      1.1  christos       return reloc_class_ifunc;
   6463      1.1  christos     case R_LARCH_RELATIVE:
   6464      1.1  christos       return reloc_class_relative;
   6465      1.1  christos     case R_LARCH_JUMP_SLOT:
   6466      1.1  christos       return reloc_class_plt;
   6467      1.1  christos     case R_LARCH_COPY:
   6468      1.1  christos       return reloc_class_copy;
   6469      1.1  christos     default:
   6470      1.1  christos       return reloc_class_normal;
   6471      1.1  christos     }
   6472      1.1  christos }
   6473      1.1  christos 
   6474      1.1  christos /* Copy the extra info we tack onto an elf_link_hash_entry.  */
   6475      1.1  christos 
   6476      1.1  christos static void
   6477      1.1  christos loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
   6478      1.1  christos 				    struct elf_link_hash_entry *dir,
   6479      1.1  christos 				    struct elf_link_hash_entry *ind)
   6480      1.1  christos {
   6481      1.1  christos   struct elf_link_hash_entry *edir, *eind;
   6482      1.1  christos 
   6483      1.1  christos   edir = dir;
   6484      1.1  christos   eind = ind;
   6485      1.1  christos 
   6486      1.1  christos   if (eind->dyn_relocs != NULL)
   6487      1.1  christos     {
   6488      1.1  christos       if (edir->dyn_relocs != NULL)
   6489      1.1  christos 	{
   6490      1.1  christos 	  struct elf_dyn_relocs **pp;
   6491      1.1  christos 	  struct elf_dyn_relocs *p;
   6492      1.1  christos 
   6493      1.1  christos 	  /* Add reloc counts against the indirect sym to the direct sym
   6494      1.1  christos 	     list.  Merge any entries against the same section.  */
   6495      1.1  christos 	  for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
   6496      1.1  christos 	    {
   6497      1.1  christos 	      struct elf_dyn_relocs *q;
   6498      1.1  christos 
   6499      1.1  christos 	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
   6500      1.1  christos 		if (q->sec == p->sec)
   6501      1.1  christos 		  {
   6502      1.1  christos 		    q->pc_count += p->pc_count;
   6503      1.1  christos 		    q->count += p->count;
   6504      1.1  christos 		    *pp = p->next;
   6505      1.1  christos 		    break;
   6506      1.1  christos 		  }
   6507      1.1  christos 	      if (q == NULL)
   6508      1.1  christos 		pp = &p->next;
   6509      1.1  christos 	    }
   6510      1.1  christos 	  *pp = edir->dyn_relocs;
   6511      1.1  christos 	}
   6512      1.1  christos 
   6513      1.1  christos       edir->dyn_relocs = eind->dyn_relocs;
   6514      1.1  christos       eind->dyn_relocs = NULL;
   6515      1.1  christos     }
   6516      1.1  christos 
   6517      1.1  christos   if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount < 0)
   6518      1.1  christos     {
   6519      1.1  christos       loongarch_elf_hash_entry(edir)->tls_type
   6520      1.1  christos 	= loongarch_elf_hash_entry(eind)->tls_type;
   6521      1.1  christos       loongarch_elf_hash_entry(eind)->tls_type = GOT_UNKNOWN;
   6522      1.1  christos     }
   6523      1.1  christos   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
   6524      1.1  christos }
   6525      1.1  christos 
   6526      1.1  christos #define PRSTATUS_SIZE		    0x1d8
   6527      1.1  christos #define PRSTATUS_OFFSET_PR_CURSIG   0xc
   6528      1.1  christos #define PRSTATUS_OFFSET_PR_PID	    0x20
   6529      1.1  christos #define ELF_GREGSET_T_SIZE	    0x168
   6530      1.1  christos #define PRSTATUS_OFFSET_PR_REG	    0x70
   6531      1.1  christos 
   6532      1.1  christos /* Support for core dump NOTE sections.  */
   6533      1.1  christos 
   6534      1.1  christos static bool
   6535      1.1  christos loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
   6536      1.1  christos {
   6537      1.1  christos   switch (note->descsz)
   6538      1.1  christos     {
   6539      1.1  christos     default:
   6540      1.1  christos       return false;
   6541      1.1  christos 
   6542      1.1  christos     /* The sizeof (struct elf_prstatus) on Linux/LoongArch.  */
   6543      1.1  christos     case PRSTATUS_SIZE:
   6544      1.1  christos       /* pr_cursig  */
   6545      1.1  christos       elf_tdata (abfd)->core->signal =
   6546      1.1  christos 	bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
   6547      1.1  christos 
   6548      1.1  christos       /* pr_pid  */
   6549      1.1  christos       elf_tdata (abfd)->core->lwpid =
   6550      1.1  christos 	bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
   6551      1.1  christos       break;
   6552      1.1  christos     }
   6553      1.1  christos 
   6554      1.1  christos   /* Make a ".reg/999" section.  */
   6555      1.1  christos   return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
   6556      1.1  christos 					  note->descpos
   6557      1.1  christos 					  + PRSTATUS_OFFSET_PR_REG);
   6558      1.1  christos }
   6559      1.1  christos 
   6560      1.1  christos #define PRPSINFO_SIZE		    0x88
   6561      1.1  christos #define PRPSINFO_OFFSET_PR_PID	    0x18
   6562      1.1  christos #define PRPSINFO_OFFSET_PR_FNAME    0x28
   6563      1.1  christos #define PRPSINFO_SIZEOF_PR_FNAME    0x10
   6564      1.1  christos #define PRPSINFO_OFFSET_PR_PS_ARGS  0x38
   6565      1.1  christos #define PRPSINFO_SIZEOF_PR_PS_ARGS  0x50
   6566      1.1  christos 
   6567      1.1  christos static bool
   6568      1.1  christos loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
   6569      1.1  christos {
   6570      1.1  christos   switch (note->descsz)
   6571      1.1  christos     {
   6572      1.1  christos     default:
   6573      1.1  christos       return false;
   6574      1.1  christos 
   6575      1.1  christos     /* The sizeof (prpsinfo_t) on Linux/LoongArch.  */
   6576      1.1  christos     case PRPSINFO_SIZE:
   6577      1.1  christos       /* pr_pid  */
   6578      1.1  christos       elf_tdata (abfd)->core->pid =
   6579      1.1  christos 	bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
   6580      1.1  christos 
   6581      1.1  christos       /* pr_fname  */
   6582      1.1  christos       elf_tdata (abfd)->core->program =
   6583      1.1  christos 	_bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
   6584      1.1  christos 			      PRPSINFO_SIZEOF_PR_FNAME);
   6585      1.1  christos 
   6586      1.1  christos       /* pr_psargs  */
   6587      1.1  christos       elf_tdata (abfd)->core->command =
   6588      1.1  christos 	_bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
   6589      1.1  christos 			      PRPSINFO_SIZEOF_PR_PS_ARGS);
   6590      1.1  christos       break;
   6591      1.1  christos     }
   6592      1.1  christos 
   6593      1.1  christos   /* Note that for some reason, a spurious space is tacked
   6594      1.1  christos      onto the end of the args in some (at least one anyway)
   6595      1.1  christos      implementations, so strip it off if it exists.  */
   6596      1.1  christos 
   6597      1.1  christos   {
   6598      1.1  christos     char *command = elf_tdata (abfd)->core->command;
   6599      1.1  christos     int n = strlen (command);
   6600      1.1  christos 
   6601      1.1  christos     if (0 < n && command[n - 1] == ' ')
   6602      1.1  christos       command[n - 1] = '\0';
   6603      1.1  christos   }
   6604      1.1  christos 
   6605      1.1  christos   return true;
   6606      1.1  christos }
   6607      1.1  christos 
   6608      1.1  christos /* Set the right mach type.  */
   6609      1.1  christos static bool
   6610      1.1  christos loongarch_elf_object_p (bfd *abfd)
   6611      1.1  christos {
   6612      1.1  christos   /* There are only two mach types in LoongArch currently.  */
   6613      1.1  christos   if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
   6614      1.1  christos     bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
   6615      1.1  christos   else
   6616      1.1  christos     bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
   6617      1.1  christos   return true;
   6618      1.1  christos }
   6619      1.1  christos 
   6620      1.1  christos static asection *
   6621      1.1  christos loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
   6622      1.1  christos 			    Elf_Internal_Rela *rel,
   6623      1.1  christos 			    struct elf_link_hash_entry *h,
   6624      1.1  christos 			    Elf_Internal_Sym *sym)
   6625      1.1  christos {
   6626      1.1  christos   if (h != NULL)
   6627      1.1  christos     switch (ELFNN_R_TYPE (rel->r_info))
   6628      1.1  christos       {
   6629      1.1  christos       case R_LARCH_GNU_VTINHERIT:
   6630      1.1  christos       case R_LARCH_GNU_VTENTRY:
   6631      1.1  christos 	return NULL;
   6632      1.1  christos       }
   6633      1.1  christos 
   6634      1.1  christos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
   6635      1.1  christos }
   6636      1.1  christos 
   6637      1.1  christos /* Return TRUE if symbol H should be hashed in the `.gnu.hash' section.  For
   6638      1.1  christos    executable PLT slots where the executable never takes the address of those
   6639      1.1  christos    functions, the function symbols are not added to the hash table.  */
   6640      1.1  christos 
   6641      1.1  christos static bool
   6642      1.1  christos elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
   6643      1.1  christos {
   6644      1.1  christos   if (h->plt.offset != (bfd_vma) -1
   6645      1.1  christos       && !h->def_regular
   6646      1.1  christos       && !h->pointer_equality_needed)
   6647      1.1  christos     return false;
   6648      1.1  christos 
   6649      1.1  christos   return _bfd_elf_hash_symbol (h);
   6650      1.1  christos }
   6651      1.1  christos 
   6652      1.1  christos #define TARGET_LITTLE_SYM loongarch_elfNN_vec
   6653      1.1  christos #define TARGET_LITTLE_NAME "elfNN-loongarch"
   6654      1.1  christos #define ELF_ARCH bfd_arch_loongarch
   6655      1.1  christos #define ELF_TARGET_ID LARCH_ELF_DATA
   6656      1.1  christos #define ELF_MACHINE_CODE EM_LOONGARCH
   6657  1.1.1.3  christos #define ELF_MINPAGESIZE 0x1000
   6658  1.1.1.3  christos #define ELF_MAXPAGESIZE 0x10000
   6659  1.1.1.3  christos #define ELF_COMMONPAGESIZE 0x4000
   6660      1.1  christos #define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
   6661      1.1  christos #define bfd_elfNN_bfd_link_hash_table_create				  \
   6662      1.1  christos   loongarch_elf_link_hash_table_create
   6663      1.1  christos #define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
   6664      1.1  christos #define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto.  */
   6665      1.1  christos #define elf_info_to_howto loongarch_info_to_howto_rela
   6666  1.1.1.3  christos #define bfd_elfNN_mkobject						  \
   6667  1.1.1.3  christos   elfNN_loongarch_object
   6668      1.1  christos #define bfd_elfNN_bfd_merge_private_bfd_data				  \
   6669      1.1  christos   elfNN_loongarch_merge_private_bfd_data
   6670      1.1  christos 
   6671      1.1  christos #define elf_backend_reloc_type_class loongarch_reloc_type_class
   6672      1.1  christos #define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
   6673      1.1  christos #define elf_backend_create_dynamic_sections				   \
   6674      1.1  christos   loongarch_elf_create_dynamic_sections
   6675      1.1  christos #define elf_backend_check_relocs loongarch_elf_check_relocs
   6676      1.1  christos #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
   6677  1.1.1.3  christos #define elf_backend_late_size_sections loongarch_elf_late_size_sections
   6678      1.1  christos #define elf_backend_relocate_section loongarch_elf_relocate_section
   6679      1.1  christos #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
   6680  1.1.1.2  christos #define elf_backend_output_arch_local_syms \
   6681  1.1.1.2  christos   elf_loongarch_output_arch_local_syms
   6682      1.1  christos #define elf_backend_finish_dynamic_sections				   \
   6683      1.1  christos   loongarch_elf_finish_dynamic_sections
   6684      1.1  christos #define elf_backend_object_p loongarch_elf_object_p
   6685      1.1  christos #define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
   6686      1.1  christos #define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
   6687      1.1  christos #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
   6688      1.1  christos #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
   6689      1.1  christos #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
   6690  1.1.1.2  christos #define bfd_elfNN_bfd_relax_section loongarch_elf_relax_section
   6691  1.1.1.3  christos #define elf_backend_size_relative_relocs loongarch_elf_size_relative_relocs
   6692  1.1.1.3  christos #define elf_backend_finish_relative_relocs \
   6693  1.1.1.3  christos   loongarch_elf_finish_relative_relocs
   6694  1.1.1.3  christos #define bfd_elfNN_new_section_hook loongarch_elf_new_section_hook
   6695  1.1.1.2  christos 
   6696  1.1.1.2  christos #define elf_backend_dtrel_excludes_plt 1
   6697      1.1  christos 
   6698      1.1  christos #include "elfNN-target.h"
   6699