Home | History | Annotate | Line # | Download | only in bfd
elfxx-loongarch.c revision 1.1.1.1
      1 /* LoongArch-specific support for ELF.
      2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
      3    Contributed by Loongson Ltd.
      4 
      5    Based on RISC-V target.
      6 
      7    This file is part of BFD, the Binary File Descriptor library.
      8 
      9    This program is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 3 of the License, or
     12    (at your option) any later version.
     13 
     14    This program is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this program; see the file COPYING3.  If not,
     21    see <http://www.gnu.org/licenses/>.  */
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 #include "libbfd.h"
     26 #include "elf-bfd.h"
     27 #include "elf/loongarch.h"
     28 #include "elfxx-loongarch.h"
     29 
     30 #define ALL_ONES (~ (bfd_vma) 0)
     31 
     32 typedef struct loongarch_reloc_howto_type_struct
     33 {
     34   /* The first must be reloc_howto_type!  */
     35   reloc_howto_type howto;
     36   bfd_reloc_code_real_type bfd_type;
     37   bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
     38 }loongarch_reloc_howto_type;
     39 
     40 #define LOONGARCH_DEFAULT_HOWTO(r_name)					    \
     41   { HOWTO (R_LARCH_##r_name, 0, 4, 32, false, 0, complain_overflow_signed,  \
     42 	bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES,	    \
     43 	false), BFD_RELOC_LARCH_##r_name, NULL }
     44 
     45 #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func,  \
     46 	    name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc)	  \
     47   { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,	  \
     48 	  inplace, src_mask, dst_mask, pcrel_off), btype, afunc }
     49 
     50 #define LOONGARCH_EMPTY_HOWTO(C) \
     51   { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL }
     52 
     53 bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *val);
     54 bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
     55 					     bfd_vma *fix_val);
     56 bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
     57 					  bfd_vma *val);
     58 
     59 
     60 /* This does not include any relocation information, but should be
     61    good enough for GDB or objdump to read the file.  */
     62 static loongarch_reloc_howto_type loongarch_howto_table[] =
     63 {
     64   /* No relocation.  */
     65     LOONGARCH_HOWTO (R_LARCH_NONE,	  /* type (0).  */
     66 	 0,				  /* rightshift */
     67 	 0,				  /* size */
     68 	 0,				  /* bitsize */
     69 	 false,				  /* pc_relative */
     70 	 0,				  /* bitpos */
     71 	 complain_overflow_dont,	  /* complain_on_overflow */
     72 	 bfd_elf_generic_reloc,		  /* special_function */
     73 	 "R_LARCH_NONE",		  /* name */
     74 	 false,				  /* partial_inplace */
     75 	 0,				  /* src_mask */
     76 	 0,				  /* dst_mask */
     77 	 false,				  /* pcrel_offset */
     78 	 BFD_RELOC_NONE,		  /* bfd_reloc_code_real_type */
     79 	 NULL),				  /* adjust_reloc_bits */
     80 
     81   /* 32 bit relocation.  */
     82   LOONGARCH_HOWTO (R_LARCH_32,		  /* type (1).  */
     83 	 0,				  /* rightshift */
     84 	 4,				  /* size */
     85 	 32,				  /* bitsize */
     86 	 false,				  /* pc_relative */
     87 	 0,				  /* bitpos */
     88 	 complain_overflow_dont,	  /* complain_on_overflow */
     89 	 bfd_elf_generic_reloc,		  /* special_function */
     90 	 "R_LARCH_32",			  /* name */
     91 	 false,				  /* partial_inplace */
     92 	 0,				  /* src_mask */
     93 	 ALL_ONES,			  /* dst_mask */
     94 	 false,				  /* pcrel_offset */
     95 	 BFD_RELOC_32,			  /* bfd_reloc_code_real_type */
     96 	 NULL),				  /* adjust_reloc_bits */
     97 
     98   /* 64 bit relocation.  */
     99   LOONGARCH_HOWTO (R_LARCH_64,		  /* type (2).  */
    100 	 0,				  /* rightshift */
    101 	 8,				  /* size */
    102 	 64,				  /* bitsize */
    103 	 false,				  /* pc_relative */
    104 	 0,				  /* bitpos */
    105 	 complain_overflow_dont,	  /* complain_on_overflow */
    106 	 bfd_elf_generic_reloc,		  /* special_function */
    107 	 "R_LARCH_64",			  /* name */
    108 	 false,				  /* partial_inplace */
    109 	 0,				  /* src_mask */
    110 	 ALL_ONES,			  /* dst_mask */
    111 	 false,				  /* pcrel_offset */
    112 	 BFD_RELOC_64,			  /* bfd_reloc_code_real_type */
    113 	 NULL),				  /* adjust_reloc_bits */
    114 
    115   LOONGARCH_HOWTO (R_LARCH_RELATIVE,	  /* type (3).  */
    116 	 0,				  /* rightshift */
    117 	 4,				  /* size */
    118 	 32,				  /* bitsize */
    119 	 false,				  /* pc_relative */
    120 	 0,				  /* bitpos */
    121 	 complain_overflow_dont,	  /* complain_on_overflow */
    122 	 bfd_elf_generic_reloc,		  /* special_function */
    123 	 "R_LARCH_RELATIVE",		  /* name */
    124 	 false,				  /* partial_inplace */
    125 	 0,				  /* src_mask */
    126 	 ALL_ONES,			  /* dst_mask */
    127 	 false,				  /* pcrel_offset */
    128 	 BFD_RELOC_NONE,		  /* undefined?  */
    129 	 NULL),				  /* adjust_reloc_bits */
    130 
    131   LOONGARCH_HOWTO (R_LARCH_COPY,	  /* type (4).  */
    132 	 0,				  /* rightshift */
    133 	 0,				  /* this one is variable size */
    134 	 0,				  /* bitsize */
    135 	 false,				  /* pc_relative */
    136 	 0,				  /* bitpos */
    137 	 complain_overflow_bitfield,	  /* complain_on_overflow */
    138 	 bfd_elf_generic_reloc,		  /* special_function */
    139 	 "R_LARCH_COPY",		  /* name */
    140 	 false,				  /* partial_inplace */
    141 	 0,				  /* src_mask */
    142 	 0,				  /* dst_mask */
    143 	 false,				  /* pcrel_offset */
    144 	 BFD_RELOC_NONE,			  /* undefined?  */
    145 	 NULL),				  /* adjust_reloc_bits */
    146 
    147   LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT,	  /* type (5).  */
    148 	 0,				  /* rightshift */
    149 	 8,				  /* size */
    150 	 64,				  /* bitsize */
    151 	 false,				  /* pc_relative */
    152 	 0,				  /* bitpos */
    153 	 complain_overflow_bitfield,	  /* complain_on_overflow */
    154 	 bfd_elf_generic_reloc,		  /* special_function */
    155 	 "R_LARCH_JUMP_SLOT",		  /* name */
    156 	 false,				  /* partial_inplace */
    157 	 0,				  /* src_mask */
    158 	 0,				  /* dst_mask */
    159 	 false,				  /* pcrel_offset */
    160 	 BFD_RELOC_NONE,			  /* undefined?  */
    161 	 NULL),				  /* adjust_reloc_bits */
    162 
    163   /* Dynamic TLS relocations.  */
    164   LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32,  /* type (6).  */
    165 	 0,				  /* rightshift */
    166 	 4,				  /* size */
    167 	 32,				  /* bitsize */
    168 	 false,				  /* pc_relative */
    169 	 0,				  /* bitpos */
    170 	 complain_overflow_dont,	  /* complain_on_overflow */
    171 	 bfd_elf_generic_reloc,		  /* special_function */
    172 	 "R_LARCH_TLS_DTPMOD32",	  /* name */
    173 	 false,				  /* partial_inplace */
    174 	 0,				  /* src_mask */
    175 	 ALL_ONES,			  /* dst_mask */
    176 	 false,				  /* pcrel_offset */
    177 	 BFD_RELOC_LARCH_TLS_DTPMOD32,	  /* bfd_reloc_code_real_type */
    178 	 NULL),				  /* adjust_reloc_bits */
    179 
    180   LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64,  /* type (7).  */
    181 	 0,				  /* rightshift */
    182 	 8,				  /* size */
    183 	 64,				  /* bitsize */
    184 	 false,				  /* pc_relative */
    185 	 0,				  /* bitpos */
    186 	 complain_overflow_dont,	  /* complain_on_overflow */
    187 	 bfd_elf_generic_reloc,		  /* special_function */
    188 	 "R_LARCH_TLS_DTPMOD64",	  /* name */
    189 	 false,				  /* partial_inplace */
    190 	 0,				  /* src_mask */
    191 	 ALL_ONES,			  /* dst_mask */
    192 	 false,				  /* pcrel_offset */
    193 	 BFD_RELOC_LARCH_TLS_DTPMOD64,	  /* bfd_reloc_code_real_type */
    194 	 NULL),				  /* adjust_reloc_bits */
    195 
    196   LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32,  /* type (8). */
    197 	 0,				  /* rightshift */
    198 	 4,				  /* size */
    199 	 32,				  /* bitsize */
    200 	 false,				  /* pc_relative */
    201 	 0,				  /* bitpos */
    202 	 complain_overflow_dont,	  /* complain_on_overflow */
    203 	 bfd_elf_generic_reloc,		  /* special_function */
    204 	 "R_LARCH_TLS_DTPREL32",	  /* name */
    205 	 true,				  /* partial_inplace */
    206 	 0,				  /* src_mask */
    207 	 ALL_ONES,			  /* dst_mask */
    208 	 false,				  /* pcrel_offset */
    209 	 BFD_RELOC_LARCH_TLS_DTPREL32,	  /* bfd_reloc_code_real_type */
    210 	 NULL),				  /* adjust_reloc_bits */
    211 
    212   LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64,  /* type (9).  */
    213 	 0,				  /* rightshift */
    214 	 8,				  /* size */
    215 	 64,				  /* bitsize */
    216 	 false,				  /* pc_relative */
    217 	 0,				  /* bitpos */
    218 	 complain_overflow_dont,	  /* complain_on_overflow */
    219 	 bfd_elf_generic_reloc,		  /* special_function */
    220 	 "R_LARCH_TLS_DTPREL64",	  /* name */
    221 	 true,				  /* partial_inplace */
    222 	 0,				  /* src_mask */
    223 	 ALL_ONES,			  /* dst_mask */
    224 	 false,				  /* pcrel_offset */
    225 	 BFD_RELOC_LARCH_TLS_DTPREL64,	  /* bfd_reloc_code_real_type */
    226 	 NULL),				  /* adjust_reloc_bits */
    227 
    228   LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32,	  /* type (10).  */
    229 	 0,				  /* rightshift */
    230 	 4,				  /* size */
    231 	 32,				  /* bitsize */
    232 	 false,				  /* pc_relative */
    233 	 0,				  /* bitpos */
    234 	 complain_overflow_dont,	  /* complain_on_overflow */
    235 	 bfd_elf_generic_reloc,		  /* special_function */
    236 	 "R_LARCH_TLS_TPREL32",		  /* name */
    237 	 false,				  /* partial_inplace */
    238 	 0,				  /* src_mask */
    239 	 ALL_ONES,			  /* dst_mask */
    240 	 false,				  /* pcrel_offset */
    241 	 BFD_RELOC_LARCH_TLS_TPREL32,	  /* bfd_reloc_code_real_type */
    242 	 NULL),				  /* adjust_reloc_bits */
    243 
    244   LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64,	  /* type (11).  */
    245 	 0,				  /* rightshift */
    246 	 8,				  /* size */
    247 	 64,				  /* bitsize */
    248 	 false,				  /* pc_relative */
    249 	 0,				  /* bitpos */
    250 	 complain_overflow_dont,	  /* complain_on_overflow */
    251 	 bfd_elf_generic_reloc,		  /* special_function */
    252 	 "R_LARCH_TLS_TPREL64",		  /* name */
    253 	 false,				  /* partial_inplace */
    254 	 0,				  /* src_mask */
    255 	 ALL_ONES,			  /* dst_mask */
    256 	 false,				  /* pcrel_offset */
    257 	 BFD_RELOC_LARCH_TLS_TPREL64,	  /* bfd_reloc_code_real_type */
    258 	 NULL),				  /* adjust_reloc_bits */
    259 
    260   LOONGARCH_HOWTO (R_LARCH_IRELATIVE,	  /* type (12).  */
    261 	 0,				  /* rightshift */
    262 	 4,				  /* size */
    263 	 32,				  /* bitsize */
    264 	 false,				  /* pc_relative */
    265 	 0,				  /* bitpos */
    266 	 complain_overflow_dont,	  /* complain_on_overflow */
    267 	 bfd_elf_generic_reloc,		  /* special_function */
    268 	 "R_LARCH_IRELATIVE",		  /* name */
    269 	 false,				  /* partial_inplace */
    270 	 0,				  /* src_mask */
    271 	 ALL_ONES,			  /* dst_mask */
    272 	 false,				  /* pcrel_offset */
    273 	 BFD_RELOC_NONE,		  /* undefined?  */
    274 	 NULL),				  /* adjust_reloc_bits */
    275 
    276   LOONGARCH_EMPTY_HOWTO(13),
    277   LOONGARCH_EMPTY_HOWTO(14),
    278   LOONGARCH_EMPTY_HOWTO(15),
    279   LOONGARCH_EMPTY_HOWTO(16),
    280   LOONGARCH_EMPTY_HOWTO(17),
    281   LOONGARCH_EMPTY_HOWTO(18),
    282   LOONGARCH_EMPTY_HOWTO(19),
    283 
    284   LOONGARCH_HOWTO (R_LARCH_MARK_LA,		/* type (20).  */
    285 	 0,				   	/* rightshift.  */
    286 	 0,				   	/* size.  */
    287 	 0,				  	/* bitsize.  */
    288 	 false,					/* pc_relative.  */
    289 	 0,				   	/* bitpos.  */
    290 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    291 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    292 	 "R_LARCH_MARK_LA",			/* name.  */
    293 	 false,			       		/* partial_inplace.  */
    294 	 0,					/* src_mask.  */
    295 	 0,					/* dst_mask.  */
    296 	 false,					/* pcrel_offset */
    297 	 BFD_RELOC_LARCH_MARK_LA,		/* bfd_reloc_code_real_type */
    298 	 NULL),					/* adjust_reloc_bits */
    299 
    300   LOONGARCH_HOWTO (R_LARCH_MARK_PCREL,		/* type (21).  */
    301 	 0,				   	/* rightshift.  */
    302 	 0,				   	/* size.  */
    303 	 0,				  	/* bitsize.  */
    304 	 false,					/* pc_relative.  */
    305 	 0,				   	/* bitpos.  */
    306 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    307 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    308 	 "R_LARCH_MARK_PCREL",			/* name.  */
    309 	 false,			       		/* partial_inplace.  */
    310 	 0,					/* src_mask.  */
    311 	 0,					/* dst_mask.  */
    312 	 false,					/* pcrel_offset */
    313 	 BFD_RELOC_LARCH_MARK_PCREL,		/* bfd_reloc_code_real_type */
    314 	 NULL),					/* adjust_reloc_bits */
    315 
    316   LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL,	/* type (22).  */
    317 	 2,				   	/* rightshift.  */
    318 	 4,				   	/* size.  */
    319 	 32,				  	/* bitsize.  */
    320 	 true /* FIXME: somewhat use this.  */,	/* pc_relative.  */
    321 	 0,				   	/* bitpos.  */
    322 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    323 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    324 	 "R_LARCH_SOP_PUSH_PCREL",	    	/* name.  */
    325 	 false,			       		/* partial_inplace.  */
    326 	 0x03ffffff,				/* src_mask.  */
    327 	 0x03ffffff,				/* dst_mask.  */
    328 	 false,					/* pcrel_offset */
    329 	 BFD_RELOC_LARCH_SOP_PUSH_PCREL,	/* bfd_reloc_code_real_type */
    330 	 NULL),					/* adjust_reloc_bits */
    331 
    332   /* type 23-37.  */
    333   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
    334   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP),
    335   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL),
    336   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL),
    337   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT),
    338   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD),
    339   LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL),
    340   LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT),
    341   LOONGARCH_DEFAULT_HOWTO (SOP_NOT),
    342   LOONGARCH_DEFAULT_HOWTO (SOP_SUB),
    343   LOONGARCH_DEFAULT_HOWTO (SOP_SL),
    344   LOONGARCH_DEFAULT_HOWTO (SOP_SR),
    345   LOONGARCH_DEFAULT_HOWTO (SOP_ADD),
    346   LOONGARCH_DEFAULT_HOWTO (SOP_AND),
    347   LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
    348 
    349   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5,	  /* type (38).  */
    350 	 0,				   	  /* rightshift.  */
    351 	 4,				   	  /* size.  */
    352 	 5,				  	  /* bitsize.  */
    353 	 false,					  /* pc_relative.  */
    354 	 10,				   	  /* bitpos.  */
    355 	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
    356 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    357 	 "R_LARCH_SOP_POP_32_S_10_5",	    	  /* name.  */
    358 	 false,			       		  /* partial_inplace.  */
    359 	 0,					  /* src_mask */
    360 	 0x7c00,				  /* dst_mask */
    361 	 false,					  /* pcrel_offset */
    362 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_5,	  /* bfd_reloc_code_real_type */
    363 	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
    364 
    365   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12,	  /* type (39).  */
    366 	 0,				   	  /* rightshift.  */
    367 	 4,				   	  /* size.  */
    368 	 12,				  	  /* bitsize.  */
    369 	 false,					  /* pc_relative.  */
    370 	 10,				   	  /* bitpos.  */
    371 	 complain_overflow_unsigned,	    	  /* complain_on_overflow.  */
    372 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    373 	 "R_LARCH_SOP_POP_32_U_10_12",	    	  /* name.  */
    374 	 false,			       		  /* partial_inplace.  */
    375 	 0,					  /* src_mask */
    376 	 0x3ffc00,				  /* dst_mask */
    377 	 false,					  /* pcrel_offset */
    378 	 BFD_RELOC_LARCH_SOP_POP_32_U_10_12,	  /* bfd_reloc_code_real_type */
    379 	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
    380 
    381   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12,	  /* type (40).  */
    382 	 0,				   	  /* rightshift.  */
    383 	 4,				   	  /* size.  */
    384 	 12,				  	  /* bitsize.  */
    385 	 false,					  /* pc_relative.  */
    386 	 10,				   	  /* bitpos.  */
    387 	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
    388 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    389 	 "R_LARCH_SOP_POP_32_S_10_12",	    	  /* name.  */
    390 	 false,			       		  /* partial_inplace.  */
    391 	 0,					  /* src_mask */
    392 	 0x3ffc00,				  /* dst_mask */
    393 	 false,					  /* pcrel_offset */
    394 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_12,	  /* bfd_reloc_code_real_type */
    395 	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
    396 
    397   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16,	  /* type (41).  */
    398 	 0,				   	  /* rightshift.  */
    399 	 4,				   	  /* size.  */
    400 	 16,				  	  /* bitsize.  */
    401 	 false,					  /* pc_relative.  */
    402 	 10,				   	  /* bitpos.  */
    403 	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
    404 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    405 	 "R_LARCH_SOP_POP_32_S_10_16",	    	  /* name.  */
    406 	 false,			       		  /* partial_inplace.  */
    407 	 0,					  /* src_mask */
    408 	 0x3fffc00,				  /* dst_mask */
    409 	 false,					  /* pcrel_offset */
    410 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_16,	  /* bfd_reloc_code_real_type */
    411 	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
    412 
    413   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42).  */
    414 	 2,					  /* rightshift.  */
    415 	 4,				   	  /* size.  */
    416 	 16,				  	  /* bitsize.  */
    417 	 false,					  /* pc_relative.  */
    418 	 10,				   	  /* bitpos.  */
    419 	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
    420 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    421 	 "R_LARCH_SOP_POP_32_S_10_16_S2",    	  /* name.  */
    422 	 false,			       		  /* partial_inplace.  */
    423 	 0,					  /* src_mask */
    424 	 0x3fffc00,				  /* dst_mask */
    425 	 false,					  /* pcrel_offset */
    426 	 BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2,	  /* bfd_reloc_code_real_type */
    427 	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
    428 
    429   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20,	  /* type (43).  */
    430 	 0,				   	  /* rightshift.  */
    431 	 4,				   	  /* size.  */
    432 	 20,				  	  /* bitsize.  */
    433 	 false,					  /* pc_relative.  */
    434 	 5,				   	  /* bitpos.  */
    435 	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
    436 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    437 	 "R_LARCH_SOP_POP_32_S_5_20",    	  /* name.  */
    438 	 false,			       		  /* partial_inplace.  */
    439 	 0,					  /* src_mask */
    440 	 0x1ffffe0,				  /* dst_mask */
    441 	 false,					  /* pcrel_offset */
    442 	 BFD_RELOC_LARCH_SOP_POP_32_S_5_20,	  /* bfd_reloc_code_real_type */
    443 	 loongarch_gen_adjust_reloc_bits),        /* adjust_reloc_bits */
    444 
    445   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
    446 						  /* type (44).  */
    447 	 2,					  /* rightshift.  */
    448 	 4,					  /* size.  */
    449 	 21,				  	  /* bitsize.  */
    450 	 false,					  /* pc_relative.  */
    451 	 0,				   	  /* bitpos.  */
    452 	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
    453 	 bfd_elf_generic_reloc,	       		  /* special_function.  */
    454 	 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2",  	  /* name.  */
    455 	 false,			       		  /* partial_inplace.  */
    456 	 0xfc0003e0,				  /* src_mask */
    457 	 0xfc0003e0,				  /* dst_mask */
    458 	 false,					  /* pcrel_offset */
    459 	 BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
    460 						  /* bfd_reloc_code_real_type */
    461 	 loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */
    462 
    463   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2,	/* type (45).  */
    464 	 2,				   	/* rightshift.  */
    465 	 4,				   	/* size.  */
    466 	 26,				  	/* bitsize.  */
    467 	 false,					/* pc_relative.  */
    468 	 0,				   	/* bitpos.  */
    469 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    470 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    471 	 "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", 	/* name.  */
    472 	 false,			       		/* partial_inplace.  */
    473 	 0xfc000000,				/* src_mask */
    474 	 0xfc000000,				/* dst_mask */
    475 	 false,					/* pcrel_offset */
    476 	 BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
    477 						/* bfd_reloc_code_real_type */
    478 	 loongarch_adjust_reloc_bits_l16_h10),	/* adjust_reloc_bits */
    479 
    480   LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U,	/* type (46).  */
    481 	 0,				   	/* rightshift.  */
    482 	 4,				   	/* size.  */
    483 	 32,				  	/* bitsize.  */
    484 	 false,					/* pc_relative.  */
    485 	 0,				   	/* bitpos.  */
    486 	 complain_overflow_unsigned,	    	/* complain_on_overflow.  */
    487 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    488 	 "R_LARCH_SOP_POP_32_S_U",    		/* name.  */
    489 	 false,			       		/* partial_inplace.  */
    490 	 0xffffffff00000000,			/* src_mask */
    491 	 0x00000000ffffffff,			/* dst_mask */
    492 	 false,					/* pcrel_offset */
    493 	 BFD_RELOC_LARCH_SOP_POP_32_U,		/* bfd_reloc_code_real_type */
    494 	 loongarch_gen_adjust_reloc_bits),	/* adjust_reloc_bits */
    495 
    496   LOONGARCH_HOWTO (R_LARCH_ADD8,	      	/* type (47).  */
    497 	 0,				   	/* rightshift.  */
    498 	 4,				   	/* size.  */
    499 	 8,				  	/* bitsize.  */
    500 	 false,					/* pc_relative.  */
    501 	 0,				   	/* bitpos.  */
    502 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    503 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    504 	 "R_LARCH_ADD8",    			/* name.  */
    505 	 false,			       		/* partial_inplace.  */
    506 	 0,					/* src_mask */
    507 	 ALL_ONES,				/* dst_mask */
    508 	 false,					/* pcrel_offset */
    509 	 BFD_RELOC_LARCH_ADD8,			/* bfd_reloc_code_real_type */
    510 	 NULL),					/* adjust_reloc_bits */
    511 
    512   LOONGARCH_HOWTO (R_LARCH_ADD16,	      	/* type (48).  */
    513 	 0,				   	/* rightshift.  */
    514 	 4,				   	/* size.  */
    515 	 16,				  	/* bitsize.  */
    516 	 false,					/* pc_relative.  */
    517 	 0,				   	/* bitpos.  */
    518 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    519 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    520 	 "R_LARCH_ADD16",    			/* name.  */
    521 	 false,			       		/* partial_inplace.  */
    522 	 0,					/* src_mask */
    523 	 ALL_ONES,				/* dst_mask */
    524 	 false,					/* pcrel_offset */
    525 	 BFD_RELOC_LARCH_ADD16,			/* bfd_reloc_code_real_type */
    526 	 NULL),					/* adjust_reloc_bits */
    527 
    528   LOONGARCH_HOWTO (R_LARCH_ADD24,	      	/* type (49).  */
    529 	 0,				   	/* rightshift.  */
    530 	 4,				   	/* size.  */
    531 	 24,				  	/* bitsize.  */
    532 	 false,					/* pc_relative.  */
    533 	 0,				   	/* bitpos.  */
    534 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    535 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    536 	 "R_LARCH_ADD24",    			/* name.  */
    537 	 false,			       		/* partial_inplace.  */
    538 	 0,					/* src_mask */
    539 	 ALL_ONES,				/* dst_mask */
    540 	 false,					/* pcrel_offset */
    541 	 BFD_RELOC_LARCH_ADD24,			/* bfd_reloc_code_real_type */
    542 	 NULL),					/* adjust_reloc_bits */
    543 
    544   LOONGARCH_HOWTO (R_LARCH_ADD32,	      	/* type (50).  */
    545 	 0,				   	/* rightshift.  */
    546 	 4,				   	/* size.  */
    547 	 32,				  	/* bitsize.  */
    548 	 false,					/* pc_relative.  */
    549 	 0,				   	/* bitpos.  */
    550 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    551 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    552 	 "R_LARCH_ADD32",    			/* name.  */
    553 	 false,			       		/* partial_inplace.  */
    554 	 0,					/* src_mask */
    555 	 ALL_ONES,				/* dst_mask */
    556 	 false,					/* pcrel_offset */
    557 	 BFD_RELOC_LARCH_ADD32,			/* bfd_reloc_code_real_type */
    558 	 NULL),					/* adjust_reloc_bits */
    559 
    560   LOONGARCH_HOWTO (R_LARCH_ADD64,	      	/* type (51).  */
    561 	 0,				   	/* rightshift.  */
    562 	 8,				   	/* size.  */
    563 	 64,				  	/* bitsize.  */
    564 	 false,					/* pc_relative.  */
    565 	 0,				   	/* bitpos.  */
    566 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    567 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    568 	 "R_LARCH_ADD64",    			/* name.  */
    569 	 false,			       		/* partial_inplace.  */
    570 	 0,					/* src_mask */
    571 	 ALL_ONES,				/* dst_mask */
    572 	 false,					/* pcrel_offset */
    573 	 BFD_RELOC_LARCH_ADD64,			/* bfd_reloc_code_real_type */
    574 	 NULL),					/* adjust_reloc_bits */
    575 
    576   LOONGARCH_HOWTO (R_LARCH_SUB8,	      	/* type (52).  */
    577 	 0,				   	/* rightshift.  */
    578 	 4,				   	/* size.  */
    579 	 8,				  	/* bitsize.  */
    580 	 false,					/* pc_relative.  */
    581 	 0,				   	/* bitpos.  */
    582 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    583 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    584 	 "R_LARCH_SUB8",    			/* name.  */
    585 	 false,			       		/* partial_inplace.  */
    586 	 0,					/* src_mask */
    587 	 ALL_ONES,				/* dst_mask */
    588 	 false,					/* pcrel_offset */
    589 	 BFD_RELOC_LARCH_SUB8,			/* bfd_reloc_code_real_type */
    590 	 NULL),					/* adjust_reloc_bits */
    591 
    592   LOONGARCH_HOWTO (R_LARCH_SUB16,	      	/* type (53).  */
    593 	 0,				   	/* rightshift.  */
    594 	 4,				   	/* size.  */
    595 	 16,				  	/* bitsize.  */
    596 	 false,					/* pc_relative.  */
    597 	 0,				   	/* bitpos.  */
    598 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    599 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    600 	 "R_LARCH_SUB16",    			/* name.  */
    601 	 false,			       		/* partial_inplace.  */
    602 	 0,					/* src_mask */
    603 	 ALL_ONES,				/* dst_mask */
    604 	 false,					/* pcrel_offset */
    605 	 BFD_RELOC_LARCH_SUB16,			/* bfd_reloc_code_real_type */
    606 	 NULL),					/* adjust_reloc_bits */
    607 
    608   LOONGARCH_HOWTO (R_LARCH_SUB24,	      	/* type (54).  */
    609 	 0,				   	/* rightshift.  */
    610 	 4,				   	/* size.  */
    611 	 24,				  	/* bitsize.  */
    612 	 false,					/* pc_relative.  */
    613 	 0,				   	/* bitpos.  */
    614 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    615 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    616 	 "R_LARCH_SUB24",    			/* name.  */
    617 	 false,			       		/* partial_inplace.  */
    618 	 0,					/* src_mask */
    619 	 ALL_ONES,				/* dst_mask */
    620 	 false,					/* pcrel_offset */
    621 	 BFD_RELOC_LARCH_SUB24,			/* bfd_reloc_code_real_type */
    622 	 NULL),					/* adjust_reloc_bits */
    623 
    624   LOONGARCH_HOWTO (R_LARCH_SUB32,	      	/* type (55).  */
    625 	 0,				   	/* rightshift.  */
    626 	 4,				   	/* size.  */
    627 	 32,				  	/* bitsize.  */
    628 	 false,					/* pc_relative.  */
    629 	 0,				   	/* bitpos.  */
    630 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    631 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    632 	 "R_LARCH_SUB32",    			/* name.  */
    633 	 false,			       		/* partial_inplace.  */
    634 	 0,					/* src_mask */
    635 	 ALL_ONES,				/* dst_mask */
    636 	 false,					/* pcrel_offset */
    637 	 BFD_RELOC_LARCH_SUB32,			/* bfd_reloc_code_real_type */
    638 	 NULL),					/* adjust_reloc_bits */
    639 
    640   LOONGARCH_HOWTO (R_LARCH_SUB64,	      	/* type (56).  */
    641 	 0,				   	/* rightshift.  */
    642 	 8,				   	/* size.  */
    643 	 64,				  	/* bitsize.  */
    644 	 false,					/* pc_relative.  */
    645 	 0,				   	/* bitpos.  */
    646 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    647 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    648 	 "R_LARCH_SUB64",    			/* name.  */
    649 	 false,			       		/* partial_inplace.  */
    650 	 0,					/* src_mask */
    651 	 ALL_ONES,				/* dst_mask */
    652 	 false,					/* pcrel_offset */
    653 	 BFD_RELOC_LARCH_SUB64,			/* bfd_reloc_code_real_type */
    654 	 NULL),					/* adjust_reloc_bits */
    655 
    656   LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT,      	/* type (57).  */
    657 	 0,				   	/* rightshift.  */
    658 	 0,				   	/* size.  */
    659 	 0,				  	/* bitsize.  */
    660 	 false,					/* pc_relative.  */
    661 	 0,				   	/* bitpos.  */
    662 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    663 	 bfd_elf_generic_reloc,	       		/* special_function.  */
    664 	 "R_LARCH_GNU_VTINHERIT",  		/* name.  */
    665 	 false,			       		/* partial_inplace.  */
    666 	 0,					/* src_mask */
    667 	 0,					/* dst_mask */
    668 	 false,					/* pcrel_offset */
    669 	 BFD_RELOC_NONE,			/* bfd_reloc_code_real_type */
    670 	 NULL),					/* adjust_reloc_bits */
    671 
    672   LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY,      	/* type (58).  */
    673 	 0,				   	/* rightshift.  */
    674 	 0,				   	/* size.  */
    675 	 0,				  	/* bitsize.  */
    676 	 false,					/* pc_relative.  */
    677 	 0,				   	/* bitpos.  */
    678 	 complain_overflow_signed,	    	/* complain_on_overflow.  */
    679 	 NULL,					/* special_function.  */
    680 	 "R_LARCH_GNU_VTENTRY",  		/* name.  */
    681 	 false,			       		/* partial_inplace.  */
    682 	 0,					/* src_mask */
    683 	 0,					/* dst_mask */
    684 	 false,					/* pcrel_offset */
    685 	 BFD_RELOC_NONE,			/* bfd_reloc_code_real_type */
    686 	 NULL),					/* adjust_reloc_bits */
    687 };
    688 
    689 reloc_howto_type *
    690 loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
    691 {
    692   if(r_type < R_LARCH_count)
    693     {
    694       /* For search table fast.  */
    695       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
    696 
    697       if (loongarch_howto_table[r_type].howto.type == r_type)
    698 	return (reloc_howto_type *)&loongarch_howto_table[r_type];
    699 
    700       BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type);
    701 
    702       for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
    703 	if (loongarch_howto_table[i].howto.type == r_type)
    704 	  return (reloc_howto_type *)&loongarch_howto_table[i];
    705     }
    706 
    707   (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
    708 			 abfd, r_type);
    709   bfd_set_error (bfd_error_bad_value);
    710   return NULL;
    711 }
    712 
    713 reloc_howto_type *
    714 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    715 {
    716   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
    717 
    718   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
    719     if (loongarch_howto_table[i].howto.name
    720 	&& strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0)
    721       return (reloc_howto_type *)&loongarch_howto_table[i];
    722 
    723   (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"),
    724 			 abfd, r_name);
    725   bfd_set_error (bfd_error_bad_value);
    726 
    727   return NULL;
    728 }
    729 
    730 /* Cost so much.  */
    731 reloc_howto_type *
    732 loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    733 			     bfd_reloc_code_real_type code)
    734 {
    735   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
    736 
    737   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
    738     if (loongarch_howto_table[i].bfd_type == code)
    739       return (reloc_howto_type *)&loongarch_howto_table[i];
    740 
    741   (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"),
    742 			 abfd, code);
    743   bfd_set_error (bfd_error_bad_value);
    744 
    745   return NULL;
    746 }
    747 
    748 #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
    749   (~((((bfd_vma)0x1) << (bitsize)) - 1))
    750 
    751 /* Adjust val to perform insn
    752  * BFD_RELOC_LARCH_SOP_POP_32_S_10_5
    753  * BFD_RELOC_LARCH_SOP_POP_32_S_10_12
    754  * BFD_RELOC_LARCH_SOP_POP_32_U_10_12
    755  * BFD_RELOC_LARCH_SOP_POP_32_S_10_16
    756  * BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
    757  * BFD_RELOC_LARCH_SOP_POP_32_S_5_20
    758  * BFD_RELOC_LARCH_SOP_POP_32_U.
    759 */
    760 
    761 bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
    762 {
    763   bfd_vma val = *fix_val;
    764   /* Check val low bits if rightshift != 0, before rightshift  */
    765   if (howto->rightshift
    766       && (((0x1UL << howto->rightshift) - 1) & val))
    767     return false;
    768 
    769   int bitsize = howto->bitsize + howto->rightshift;
    770 
    771   /* Return false if overflow.  */
    772   if (howto->complain_on_overflow == complain_overflow_signed)
    773     {
    774       bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
    775       /* If val < 0.  */
    776       if (sig_bit)
    777 	{
    778 	  if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
    779 	      != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
    780 	    return false;
    781 	}
    782       else
    783 	{
    784 	  if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
    785 	    return false;
    786 	}
    787     }
    788   else if (howto->complain_on_overflow == complain_overflow_unsigned)
    789     {
    790       if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
    791 	return false;
    792     }
    793   else
    794     return false;
    795 
    796   /* Perform insn bits field.  */
    797   val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
    798   val <<= howto->bitpos;
    799 
    800   *fix_val = val;
    801 
    802   return true;
    803 }
    804 
    805 /* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2.  */
    806 bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
    807 					     bfd_vma *fix_val)
    808 {
    809   bfd_vma val = *fix_val;
    810   /* Check val low bits if rightshift != 0, before rightshift  */
    811   if (howto->rightshift
    812       && (((0x1UL << howto->rightshift) - 1) & val))
    813     return false;
    814 
    815   /* Return false if overflow.  */
    816   if (howto->complain_on_overflow != complain_overflow_signed)
    817     return false;
    818 
    819   int bitsize = howto->bitsize + howto->rightshift;
    820   bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
    821   /* If val < 0.  */
    822   if (sig_bit)
    823     {
    824       if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
    825 	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
    826 	return false;
    827     }
    828   else
    829     {
    830       if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
    831 	return false;
    832     }
    833 
    834   /* Perform insn bits field.  */
    835   val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
    836 
    837   /* Perform insn bits field. 20:16>>16, 15:0<<10 */
    838   val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
    839 
    840   *fix_val = val;
    841 
    842   return true;
    843 }
    844 
    845 /* Reloc type R_LARCH_SOP_POP_32_S_0_10_10_16_S2.  */
    846 bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
    847 					  bfd_vma *fix_val)
    848 {
    849   bfd_vma val = *fix_val;
    850   /* Check val low bits if rightshift != 0, before rightshift  */
    851   if (howto->rightshift
    852       && (((0x1UL << howto->rightshift) - 1) & val))
    853     return false;
    854 
    855   /* Return false if overflow.  */
    856   if (howto->complain_on_overflow != complain_overflow_signed)
    857     return false;
    858 
    859   int bitsize = howto->bitsize + howto->rightshift;
    860   bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
    861   /* If val < 0.  */
    862   if (sig_bit)
    863     {
    864       if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
    865 	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
    866 	return false;
    867     }
    868   else
    869     {
    870       if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
    871 	return false;
    872     }
    873 
    874   /* Perform insn bits field.  */
    875   val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
    876 
    877   /* Perform insn bits field. 25:16>>16, 15:0<<10 */
    878   val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
    879 
    880   *fix_val = val;
    881 
    882   return true;
    883 }
    884 
    885 bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
    886 				       bfd_vma *fix_val)
    887 {
    888   BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
    889   return ((loongarch_reloc_howto_type *)
    890 	  howto)->adjust_reloc_bits(howto, fix_val);
    891 }
    892