gprofng: fix build with -mx32
[binutils-gdb/blckswan.git] / bfd / elfxx-loongarch.c
blob6f7c82297c5b1f883817361b5651d6eb3828ad31
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/>. */
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"
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,
55 bfd_vma *fix_val);
56 bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
57 bfd_vma *val);
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[] =
64 /* No relocation. */
65 LOONGARCH_HOWTO (R_LARCH_NONE, /* type (0). */
66 0, /* rightshift */
67 3, /* 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 */
81 /* 32 bit relocation. */
82 LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */
83 0, /* rightshift */
84 2, /* 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 */
98 /* 64 bit relocation. */
99 LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */
100 0, /* rightshift */
101 4, /* 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 */
115 LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */
116 0, /* rightshift */
117 2, /* 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 */
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 */
147 LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */
148 0, /* rightshift */
149 4, /* 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 */
163 /* Dynamic TLS relocations. */
164 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */
165 0, /* rightshift */
166 2, /* 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 */
180 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */
181 0, /* rightshift */
182 4, /* 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 */
196 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */
197 0, /* rightshift */
198 2, /* 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 */
212 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */
213 0, /* rightshift */
214 4, /* 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 */
228 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */
229 0, /* rightshift */
230 2, /* 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 */
244 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */
245 0, /* rightshift */
246 4, /* 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 */
260 LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */
261 0, /* rightshift */
262 2, /* 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 */
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). */
285 0, /* rightshift. */
286 3, /* 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 */
300 LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
301 0, /* rightshift. */
302 3, /* 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 */
316 LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
317 2, /* rightshift. */
318 2, /* 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 */
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),
349 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */
350 0, /* rightshift. */
351 2, /* 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 */
365 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */
366 0, /* rightshift. */
367 2, /* 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 */
381 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */
382 0, /* rightshift. */
383 2, /* 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 */
397 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */
398 0, /* rightshift. */
399 2, /* 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 */
413 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */
414 2, /* rightshift. */
415 2, /* 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 */
429 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */
430 0, /* rightshift. */
431 2, /* 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 */
445 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
446 /* type (44). */
447 2, /* rightshift. */
448 2, /* 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 */
463 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
464 2, /* rightshift. */
465 2, /* 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 */
480 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
481 0, /* rightshift. */
482 2, /* 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 */
496 LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
497 0, /* rightshift. */
498 2, /* 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 */
512 LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
513 0, /* rightshift. */
514 2, /* 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 */
528 LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
529 0, /* rightshift. */
530 2, /* 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 */
544 LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
545 0, /* rightshift. */
546 2, /* 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 */
560 LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
561 0, /* rightshift. */
562 4, /* 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 */
576 LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
577 0, /* rightshift. */
578 2, /* 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 */
592 LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
593 0, /* rightshift. */
594 2, /* 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 */
608 LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
609 0, /* rightshift. */
610 2, /* 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 */
624 LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
625 0, /* rightshift. */
626 2, /* 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 */
640 LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
641 0, /* rightshift. */
642 4, /* 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 */
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 */
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 */
689 reloc_howto_type *
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"),
708 abfd, r_type);
709 bfd_set_error (bfd_error_bad_value);
710 return NULL;
713 reloc_howto_type *
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"),
724 abfd, r_name);
725 bfd_set_error (bfd_error_bad_value);
727 return NULL;
730 /* Cost so much. */
731 reloc_howto_type *
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"),
742 abfd, code);
743 bfd_set_error (bfd_error_bad_value);
745 return NULL;
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))
767 return false;
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;
775 /* If val < 0. */
776 if (sig_bit)
778 if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
779 != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
780 return false;
782 else
784 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
785 return false;
788 else if (howto->complain_on_overflow == complain_overflow_unsigned)
790 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
791 return false;
793 else
794 return false;
796 /* Perform insn bits field. */
797 val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
798 val <<= howto->bitpos;
800 *fix_val = val;
802 return true;
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)
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;
815 /* Return false if overflow. */
816 if (howto->complain_on_overflow != complain_overflow_signed)
817 return false;
819 int bitsize = howto->bitsize + howto->rightshift;
820 bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
821 /* If val < 0. */
822 if (sig_bit)
824 if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
825 != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
826 return false;
828 else
830 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
831 return false;
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);
840 *fix_val = val;
842 return true;
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)
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;
855 /* Return false if overflow. */
856 if (howto->complain_on_overflow != complain_overflow_signed)
857 return false;
859 int bitsize = howto->bitsize + howto->rightshift;
860 bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
861 /* If val < 0. */
862 if (sig_bit)
864 if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
865 != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
866 return false;
868 else
870 if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
871 return false;
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);
880 *fix_val = val;
882 return true;
885 bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
886 bfd_vma *fix_val)
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);