1 /* LoongArch-specific support for ELF.
2 Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
5 Based on RISC-V target.
7 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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/>. */
27 #include "elf/loongarch.h"
28 #include "elfxx-loongarch.h"
30 #define ALL_ONES (~ (bfd_vma) 0)
32 typedef struct loongarch_reloc_howto_type_struct
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
;
40 #define LOONGARCH_DEFAULT_HOWTO(r_name) \
41 { HOWTO (R_LARCH_##r_name, 0, 2, 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 }
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 }
50 #define LOONGARCH_EMPTY_HOWTO(C) \
51 { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL }
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
,
56 bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type
*howto
,
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
[] =
65 LOONGARCH_HOWTO (R_LARCH_NONE
, /* type (0). */
69 false, /* pc_relative */
71 complain_overflow_dont
, /* complain_on_overflow */
72 bfd_elf_generic_reloc
, /* special_function */
73 "R_LARCH_NONE", /* name */
74 false, /* partial_inplace */
77 false, /* pcrel_offset */
78 BFD_RELOC_NONE
, /* bfd_reloc_code_real_type */
79 NULL
), /* adjust_reloc_bits */
81 /* 32 bit relocation. */
82 LOONGARCH_HOWTO (R_LARCH_32
, /* type (1). */
86 false, /* pc_relative */
88 complain_overflow_dont
, /* complain_on_overflow */
89 bfd_elf_generic_reloc
, /* special_function */
90 "R_LARCH_32", /* name */
91 false, /* partial_inplace */
93 ALL_ONES
, /* dst_mask */
94 false, /* pcrel_offset */
95 BFD_RELOC_32
, /* bfd_reloc_code_real_type */
96 NULL
), /* adjust_reloc_bits */
98 /* 64 bit relocation. */
99 LOONGARCH_HOWTO (R_LARCH_64
, /* type (2). */
103 false, /* pc_relative */
105 complain_overflow_dont
, /* complain_on_overflow */
106 bfd_elf_generic_reloc
, /* special_function */
107 "R_LARCH_64", /* name */
108 false, /* partial_inplace */
110 ALL_ONES
, /* dst_mask */
111 false, /* pcrel_offset */
112 BFD_RELOC_64
, /* bfd_reloc_code_real_type */
113 NULL
), /* adjust_reloc_bits */
115 LOONGARCH_HOWTO (R_LARCH_RELATIVE
, /* type (3). */
119 false, /* pc_relative */
121 complain_overflow_dont
, /* complain_on_overflow */
122 bfd_elf_generic_reloc
, /* special_function */
123 "R_LARCH_RELATIVE", /* name */
124 false, /* partial_inplace */
126 ALL_ONES
, /* dst_mask */
127 false, /* pcrel_offset */
128 BFD_RELOC_NONE
, /* undefined? */
129 NULL
), /* adjust_reloc_bits */
131 LOONGARCH_HOWTO (R_LARCH_COPY
, /* type (4). */
133 0, /* this one is variable size */
135 false, /* pc_relative */
137 complain_overflow_bitfield
, /* complain_on_overflow */
138 bfd_elf_generic_reloc
, /* special_function */
139 "R_LARCH_COPY", /* name */
140 false, /* partial_inplace */
143 false, /* pcrel_offset */
144 BFD_RELOC_NONE
, /* undefined? */
145 NULL
), /* adjust_reloc_bits */
147 LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT
, /* type (5). */
151 false, /* pc_relative */
153 complain_overflow_bitfield
, /* complain_on_overflow */
154 bfd_elf_generic_reloc
, /* special_function */
155 "R_LARCH_JUMP_SLOT", /* name */
156 false, /* partial_inplace */
159 false, /* pcrel_offset */
160 BFD_RELOC_NONE
, /* undefined? */
161 NULL
), /* adjust_reloc_bits */
163 /* Dynamic TLS relocations. */
164 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32
, /* type (6). */
168 false, /* pc_relative */
170 complain_overflow_dont
, /* complain_on_overflow */
171 bfd_elf_generic_reloc
, /* special_function */
172 "R_LARCH_TLS_DTPMOD32", /* name */
173 false, /* partial_inplace */
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 */
180 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64
, /* type (7). */
184 false, /* pc_relative */
186 complain_overflow_dont
, /* complain_on_overflow */
187 bfd_elf_generic_reloc
, /* special_function */
188 "R_LARCH_TLS_DTPMOD64", /* name */
189 false, /* partial_inplace */
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 */
196 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32
, /* type (8). */
200 false, /* pc_relative */
202 complain_overflow_dont
, /* complain_on_overflow */
203 bfd_elf_generic_reloc
, /* special_function */
204 "R_LARCH_TLS_DTPREL32", /* name */
205 true, /* partial_inplace */
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 */
212 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64
, /* type (9). */
216 false, /* pc_relative */
218 complain_overflow_dont
, /* complain_on_overflow */
219 bfd_elf_generic_reloc
, /* special_function */
220 "R_LARCH_TLS_DTPREL64", /* name */
221 true, /* partial_inplace */
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 */
228 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32
, /* type (10). */
232 false, /* pc_relative */
234 complain_overflow_dont
, /* complain_on_overflow */
235 bfd_elf_generic_reloc
, /* special_function */
236 "R_LARCH_TLS_TPREL32", /* name */
237 false, /* partial_inplace */
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 */
244 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64
, /* type (11). */
248 false, /* pc_relative */
250 complain_overflow_dont
, /* complain_on_overflow */
251 bfd_elf_generic_reloc
, /* special_function */
252 "R_LARCH_TLS_TPREL64", /* name */
253 false, /* partial_inplace */
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 */
260 LOONGARCH_HOWTO (R_LARCH_IRELATIVE
, /* type (12). */
264 false, /* pc_relative */
266 complain_overflow_dont
, /* complain_on_overflow */
267 bfd_elf_generic_reloc
, /* special_function */
268 "R_LARCH_IRELATIVE", /* name */
269 false, /* partial_inplace */
271 ALL_ONES
, /* dst_mask */
272 false, /* pcrel_offset */
273 BFD_RELOC_NONE
, /* undefined? */
274 NULL
), /* adjust_reloc_bits */
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),
284 LOONGARCH_HOWTO (R_LARCH_MARK_LA
, /* type (20). */
288 false, /* pc_relative. */
290 complain_overflow_signed
, /* complain_on_overflow. */
291 bfd_elf_generic_reloc
, /* special_function. */
292 "R_LARCH_MARK_LA", /* name. */
293 false, /* partial_inplace. */
296 false, /* pcrel_offset */
297 BFD_RELOC_LARCH_MARK_LA
, /* bfd_reloc_code_real_type */
298 NULL
), /* adjust_reloc_bits */
300 LOONGARCH_HOWTO (R_LARCH_MARK_PCREL
, /* type (21). */
304 false, /* pc_relative. */
306 complain_overflow_signed
, /* complain_on_overflow. */
307 bfd_elf_generic_reloc
, /* special_function. */
308 "R_LARCH_MARK_PCREL", /* name. */
309 false, /* partial_inplace. */
312 false, /* pcrel_offset */
313 BFD_RELOC_LARCH_MARK_PCREL
, /* bfd_reloc_code_real_type */
314 NULL
), /* adjust_reloc_bits */
316 LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL
, /* type (22). */
320 true /* FIXME: somewhat use this. */, /* pc_relative. */
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 */
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
),
349 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5
, /* type (38). */
353 false, /* pc_relative. */
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. */
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 */
365 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12
, /* type (39). */
369 false, /* pc_relative. */
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. */
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 */
381 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12
, /* type (40). */
385 false, /* pc_relative. */
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. */
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 */
397 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16
, /* type (41). */
401 false, /* pc_relative. */
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. */
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 */
413 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2
, /* type (42). */
417 false, /* pc_relative. */
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. */
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 */
429 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20
, /* type (43). */
433 false, /* pc_relative. */
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. */
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 */
445 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2
,
450 false, /* pc_relative. */
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 */
463 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2
, /* type (45). */
467 false, /* pc_relative. */
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 */
480 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U
, /* type (46). */
484 false, /* pc_relative. */
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 */
496 LOONGARCH_HOWTO (R_LARCH_ADD8
, /* type (47). */
500 false, /* pc_relative. */
502 complain_overflow_signed
, /* complain_on_overflow. */
503 bfd_elf_generic_reloc
, /* special_function. */
504 "R_LARCH_ADD8", /* name. */
505 false, /* partial_inplace. */
507 ALL_ONES
, /* dst_mask */
508 false, /* pcrel_offset */
509 BFD_RELOC_LARCH_ADD8
, /* bfd_reloc_code_real_type */
510 NULL
), /* adjust_reloc_bits */
512 LOONGARCH_HOWTO (R_LARCH_ADD16
, /* type (48). */
516 false, /* pc_relative. */
518 complain_overflow_signed
, /* complain_on_overflow. */
519 bfd_elf_generic_reloc
, /* special_function. */
520 "R_LARCH_ADD16", /* name. */
521 false, /* partial_inplace. */
523 ALL_ONES
, /* dst_mask */
524 false, /* pcrel_offset */
525 BFD_RELOC_LARCH_ADD16
, /* bfd_reloc_code_real_type */
526 NULL
), /* adjust_reloc_bits */
528 LOONGARCH_HOWTO (R_LARCH_ADD24
, /* type (49). */
532 false, /* pc_relative. */
534 complain_overflow_signed
, /* complain_on_overflow. */
535 bfd_elf_generic_reloc
, /* special_function. */
536 "R_LARCH_ADD24", /* name. */
537 false, /* partial_inplace. */
539 ALL_ONES
, /* dst_mask */
540 false, /* pcrel_offset */
541 BFD_RELOC_LARCH_ADD24
, /* bfd_reloc_code_real_type */
542 NULL
), /* adjust_reloc_bits */
544 LOONGARCH_HOWTO (R_LARCH_ADD32
, /* type (50). */
548 false, /* pc_relative. */
550 complain_overflow_signed
, /* complain_on_overflow. */
551 bfd_elf_generic_reloc
, /* special_function. */
552 "R_LARCH_ADD32", /* name. */
553 false, /* partial_inplace. */
555 ALL_ONES
, /* dst_mask */
556 false, /* pcrel_offset */
557 BFD_RELOC_LARCH_ADD32
, /* bfd_reloc_code_real_type */
558 NULL
), /* adjust_reloc_bits */
560 LOONGARCH_HOWTO (R_LARCH_ADD64
, /* type (51). */
564 false, /* pc_relative. */
566 complain_overflow_signed
, /* complain_on_overflow. */
567 bfd_elf_generic_reloc
, /* special_function. */
568 "R_LARCH_ADD64", /* name. */
569 false, /* partial_inplace. */
571 ALL_ONES
, /* dst_mask */
572 false, /* pcrel_offset */
573 BFD_RELOC_LARCH_ADD64
, /* bfd_reloc_code_real_type */
574 NULL
), /* adjust_reloc_bits */
576 LOONGARCH_HOWTO (R_LARCH_SUB8
, /* type (52). */
580 false, /* pc_relative. */
582 complain_overflow_signed
, /* complain_on_overflow. */
583 bfd_elf_generic_reloc
, /* special_function. */
584 "R_LARCH_SUB8", /* name. */
585 false, /* partial_inplace. */
587 ALL_ONES
, /* dst_mask */
588 false, /* pcrel_offset */
589 BFD_RELOC_LARCH_SUB8
, /* bfd_reloc_code_real_type */
590 NULL
), /* adjust_reloc_bits */
592 LOONGARCH_HOWTO (R_LARCH_SUB16
, /* type (53). */
596 false, /* pc_relative. */
598 complain_overflow_signed
, /* complain_on_overflow. */
599 bfd_elf_generic_reloc
, /* special_function. */
600 "R_LARCH_SUB16", /* name. */
601 false, /* partial_inplace. */
603 ALL_ONES
, /* dst_mask */
604 false, /* pcrel_offset */
605 BFD_RELOC_LARCH_SUB16
, /* bfd_reloc_code_real_type */
606 NULL
), /* adjust_reloc_bits */
608 LOONGARCH_HOWTO (R_LARCH_SUB24
, /* type (54). */
612 false, /* pc_relative. */
614 complain_overflow_signed
, /* complain_on_overflow. */
615 bfd_elf_generic_reloc
, /* special_function. */
616 "R_LARCH_SUB24", /* name. */
617 false, /* partial_inplace. */
619 ALL_ONES
, /* dst_mask */
620 false, /* pcrel_offset */
621 BFD_RELOC_LARCH_SUB24
, /* bfd_reloc_code_real_type */
622 NULL
), /* adjust_reloc_bits */
624 LOONGARCH_HOWTO (R_LARCH_SUB32
, /* type (55). */
628 false, /* pc_relative. */
630 complain_overflow_signed
, /* complain_on_overflow. */
631 bfd_elf_generic_reloc
, /* special_function. */
632 "R_LARCH_SUB32", /* name. */
633 false, /* partial_inplace. */
635 ALL_ONES
, /* dst_mask */
636 false, /* pcrel_offset */
637 BFD_RELOC_LARCH_SUB32
, /* bfd_reloc_code_real_type */
638 NULL
), /* adjust_reloc_bits */
640 LOONGARCH_HOWTO (R_LARCH_SUB64
, /* type (56). */
644 false, /* pc_relative. */
646 complain_overflow_signed
, /* complain_on_overflow. */
647 bfd_elf_generic_reloc
, /* special_function. */
648 "R_LARCH_SUB64", /* name. */
649 false, /* partial_inplace. */
651 ALL_ONES
, /* dst_mask */
652 false, /* pcrel_offset */
653 BFD_RELOC_LARCH_SUB64
, /* bfd_reloc_code_real_type */
654 NULL
), /* adjust_reloc_bits */
656 LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT
, /* type (57). */
660 false, /* pc_relative. */
662 complain_overflow_signed
, /* complain_on_overflow. */
663 bfd_elf_generic_reloc
, /* special_function. */
664 "R_LARCH_GNU_VTINHERIT", /* name. */
665 false, /* partial_inplace. */
668 false, /* pcrel_offset */
669 BFD_RELOC_NONE
, /* bfd_reloc_code_real_type */
670 NULL
), /* adjust_reloc_bits */
672 LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY
, /* type (58). */
676 false, /* pc_relative. */
678 complain_overflow_signed
, /* complain_on_overflow. */
679 NULL
, /* special_function. */
680 "R_LARCH_GNU_VTENTRY", /* name. */
681 false, /* partial_inplace. */
684 false, /* pcrel_offset */
685 BFD_RELOC_NONE
, /* bfd_reloc_code_real_type */
686 NULL
), /* adjust_reloc_bits */
690 loongarch_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
692 if(r_type
< R_LARCH_count
)
694 /* For search table fast. */
695 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table
) == R_LARCH_count
);
697 if (loongarch_howto_table
[r_type
].howto
.type
== r_type
)
698 return (reloc_howto_type
*)&loongarch_howto_table
[r_type
];
700 BFD_ASSERT (loongarch_howto_table
[r_type
].howto
.type
== r_type
);
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
];
707 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
709 bfd_set_error (bfd_error_bad_value
);
714 loongarch_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
716 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table
) == R_LARCH_count
);
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
];
723 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %s"),
725 bfd_set_error (bfd_error_bad_value
);
732 loongarch_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
733 bfd_reloc_code_real_type code
)
735 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table
) == R_LARCH_count
);
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
];
741 (*_bfd_error_handler
) (_("%pB: unsupported bfd relocation type %#x"),
743 bfd_set_error (bfd_error_bad_value
);
748 #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
749 (~((((bfd_vma)0x1) << (bitsize)) - 1))
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.
761 bool loongarch_gen_adjust_reloc_bits (reloc_howto_type
*howto
, bfd_vma
*fix_val
)
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
))
769 int bitsize
= howto
->bitsize
+ howto
->rightshift
;
771 /* Return false if overflow. */
772 if (howto
->complain_on_overflow
== complain_overflow_signed
)
774 bfd_vma sig_bit
= (val
>> (bitsize
- 1)) & 0x1;
778 if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1) & val
)
779 != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1))
784 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1) & val
)
788 else if (howto
->complain_on_overflow
== complain_overflow_unsigned
)
790 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
) & val
)
796 /* Perform insn bits field. */
797 val
= (val
& ((0x1U
<< bitsize
) - 1)) >> howto
->rightshift
;
798 val
<<= howto
->bitpos
;
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
,
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
))
815 /* Return false if overflow. */
816 if (howto
->complain_on_overflow
!= complain_overflow_signed
)
819 int bitsize
= howto
->bitsize
+ howto
->rightshift
;
820 bfd_vma sig_bit
= (val
>> (bitsize
- 1)) & 0x1;
824 if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1) & val
)
825 != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1))
830 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1) & val
)
834 /* Perform insn bits field. */
835 val
= (val
& ((0x1U
<< bitsize
) - 1)) >> howto
->rightshift
;
837 /* Perform insn bits field. 20:16>>16, 15:0<<10 */
838 val
= ((val
& 0xffff) << 10) | ((val
>> 16) & 0x1f);
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
,
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
))
855 /* Return false if overflow. */
856 if (howto
->complain_on_overflow
!= complain_overflow_signed
)
859 int bitsize
= howto
->bitsize
+ howto
->rightshift
;
860 bfd_vma sig_bit
= (val
>> (bitsize
- 1)) & 0x1;
864 if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1) & val
)
865 != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1))
870 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize
- 1) & val
)
874 /* Perform insn bits field. */
875 val
= (val
& ((0x1U
<< bitsize
) - 1)) >> howto
->rightshift
;
877 /* Perform insn bits field. 25:16>>16, 15:0<<10 */
878 val
= ((val
& 0xffff) << 10) | ((val
>> 16) & 0x3ff);
885 bool loongarch_adjust_reloc_bitsfield (reloc_howto_type
*howto
,
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
);