]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elfxx-loongarch.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / bfd / elfxx-loongarch.c
1 /* LoongArch-specific support for ELF.
2 Copyright (C) 2021-2023 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)(bfd *, reloc_howto_type *, bfd_vma *);
38 const char *larch_reloc_type_name;
39 } loongarch_reloc_howto_type;
40
41 #define LOONGARCH_DEFAULT_HOWTO(r_name) \
42 { HOWTO (R_LARCH_##r_name, 0, 4, 32, false, 0, complain_overflow_signed, \
43 bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES, \
44 false), BFD_RELOC_LARCH_##r_name, NULL, NULL }
45
46 #define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \
47 name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc,lname) \
48 { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \
49 inplace, src_mask, dst_mask, pcrel_off), btype, afunc, lname }
50
51 #define LOONGARCH_EMPTY_HOWTO(C) \
52 { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL }
53
54 static bool
55 reloc_bits (bfd *abfd, reloc_howto_type *howto, bfd_vma *val);
56 static bool
57 reloc_sign_bits (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val);
58
59 static bfd_reloc_status_type
60 loongarch_elf_add_sub_reloc (bfd *, arelent *, asymbol *, void *,
61 asection *, bfd *, char **);
62
63 static bfd_reloc_status_type
64 loongarch_elf_add_sub_reloc_uleb128 (bfd *, arelent *, asymbol *, void *,
65 asection *, bfd *, char **);
66
67 /* This does not include any relocation information, but should be
68 good enough for GDB or objdump to read the file. */
69 static loongarch_reloc_howto_type loongarch_howto_table[] =
70 {
71 /* No relocation. */
72 LOONGARCH_HOWTO (R_LARCH_NONE, /* type (0). */
73 0, /* rightshift */
74 0, /* size */
75 0, /* bitsize */
76 false, /* pc_relative */
77 0, /* bitpos */
78 complain_overflow_dont, /* complain_on_overflow */
79 bfd_elf_generic_reloc, /* special_function */
80 "R_LARCH_NONE", /* name */
81 false, /* partial_inplace */
82 0, /* src_mask */
83 0, /* dst_mask */
84 false, /* pcrel_offset */
85 BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
86 NULL, /* adjust_reloc_bits */
87 NULL), /* larch_reloc_type_name */
88
89 /* 32 bit relocation. */
90 LOONGARCH_HOWTO (R_LARCH_32, /* type (1). */
91 0, /* rightshift */
92 4, /* size */
93 32, /* bitsize */
94 false, /* pc_relative */
95 0, /* bitpos */
96 complain_overflow_dont, /* complain_on_overflow */
97 bfd_elf_generic_reloc, /* special_function */
98 "R_LARCH_32", /* name */
99 false, /* partial_inplace */
100 0, /* src_mask */
101 ALL_ONES, /* dst_mask */
102 false, /* pcrel_offset */
103 BFD_RELOC_32, /* bfd_reloc_code_real_type */
104 NULL, /* adjust_reloc_bits */
105 NULL), /* larch_reloc_type_name */
106
107 /* 64 bit relocation. */
108 LOONGARCH_HOWTO (R_LARCH_64, /* type (2). */
109 0, /* rightshift */
110 8, /* size */
111 64, /* bitsize */
112 false, /* pc_relative */
113 0, /* bitpos */
114 complain_overflow_dont, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_LARCH_64", /* name */
117 false, /* partial_inplace */
118 0, /* src_mask */
119 ALL_ONES, /* dst_mask */
120 false, /* pcrel_offset */
121 BFD_RELOC_64, /* bfd_reloc_code_real_type */
122 NULL, /* adjust_reloc_bits */
123 NULL), /* larch_reloc_type_name */
124
125 LOONGARCH_HOWTO (R_LARCH_RELATIVE, /* type (3). */
126 0, /* rightshift */
127 4, /* size */
128 32, /* bitsize */
129 false, /* pc_relative */
130 0, /* bitpos */
131 complain_overflow_dont, /* complain_on_overflow */
132 bfd_elf_generic_reloc, /* special_function */
133 "R_LARCH_RELATIVE", /* name */
134 false, /* partial_inplace */
135 0, /* src_mask */
136 ALL_ONES, /* dst_mask */
137 false, /* pcrel_offset */
138 BFD_RELOC_NONE, /* undefined? */
139 NULL, /* adjust_reloc_bits */
140 NULL), /* larch_reloc_type_name */
141
142 LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */
143 0, /* rightshift */
144 0, /* this one is variable size */
145 0, /* bitsize */
146 false, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_bitfield, /* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_LARCH_COPY", /* name */
151 false, /* partial_inplace */
152 0, /* src_mask */
153 0, /* dst_mask */
154 false, /* pcrel_offset */
155 BFD_RELOC_NONE, /* undefined? */
156 NULL, /* adjust_reloc_bits */
157 NULL), /* larch_reloc_type_name */
158
159 LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT, /* type (5). */
160 0, /* rightshift */
161 8, /* size */
162 64, /* bitsize */
163 false, /* pc_relative */
164 0, /* bitpos */
165 complain_overflow_bitfield, /* complain_on_overflow */
166 bfd_elf_generic_reloc, /* special_function */
167 "R_LARCH_JUMP_SLOT", /* name */
168 false, /* partial_inplace */
169 0, /* src_mask */
170 0, /* dst_mask */
171 false, /* pcrel_offset */
172 BFD_RELOC_NONE, /* undefined? */
173 NULL, /* adjust_reloc_bits */
174 NULL), /* larch_reloc_type_name */
175
176 /* Dynamic TLS relocations. */
177 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32, /* type (6). */
178 0, /* rightshift */
179 4, /* size */
180 32, /* bitsize */
181 false, /* pc_relative */
182 0, /* bitpos */
183 complain_overflow_dont, /* complain_on_overflow */
184 bfd_elf_generic_reloc, /* special_function */
185 "R_LARCH_TLS_DTPMOD32", /* name */
186 false, /* partial_inplace */
187 0, /* src_mask */
188 ALL_ONES, /* dst_mask */
189 false, /* pcrel_offset */
190 BFD_RELOC_LARCH_TLS_DTPMOD32, /* bfd_reloc_code_real_type */
191 NULL, /* adjust_reloc_bits */
192 NULL), /* larch_reloc_type_name */
193
194 LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64, /* type (7). */
195 0, /* rightshift */
196 8, /* size */
197 64, /* bitsize */
198 false, /* pc_relative */
199 0, /* bitpos */
200 complain_overflow_dont, /* complain_on_overflow */
201 bfd_elf_generic_reloc, /* special_function */
202 "R_LARCH_TLS_DTPMOD64", /* name */
203 false, /* partial_inplace */
204 0, /* src_mask */
205 ALL_ONES, /* dst_mask */
206 false, /* pcrel_offset */
207 BFD_RELOC_LARCH_TLS_DTPMOD64, /* bfd_reloc_code_real_type */
208 NULL, /* adjust_reloc_bits */
209 NULL), /* larch_reloc_type_name */
210
211 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32, /* type (8). */
212 0, /* rightshift */
213 4, /* size */
214 32, /* bitsize */
215 false, /* pc_relative */
216 0, /* bitpos */
217 complain_overflow_dont, /* complain_on_overflow */
218 bfd_elf_generic_reloc, /* special_function */
219 "R_LARCH_TLS_DTPREL32", /* name */
220 true, /* partial_inplace */
221 0, /* src_mask */
222 ALL_ONES, /* dst_mask */
223 false, /* pcrel_offset */
224 BFD_RELOC_LARCH_TLS_DTPREL32, /* bfd_reloc_code_real_type */
225 NULL, /* adjust_reloc_bits */
226 NULL), /* larch_reloc_type_name */
227
228 LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64, /* type (9). */
229 0, /* rightshift */
230 8, /* size */
231 64, /* 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_DTPREL64", /* name */
237 true, /* partial_inplace */
238 0, /* src_mask */
239 ALL_ONES, /* dst_mask */
240 false, /* pcrel_offset */
241 BFD_RELOC_LARCH_TLS_DTPREL64, /* bfd_reloc_code_real_type */
242 NULL, /* adjust_reloc_bits */
243 NULL), /* larch_reloc_type_name */
244
245 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32, /* type (10). */
246 0, /* rightshift */
247 4, /* size */
248 32, /* bitsize */
249 false, /* pc_relative */
250 0, /* bitpos */
251 complain_overflow_dont, /* complain_on_overflow */
252 bfd_elf_generic_reloc, /* special_function */
253 "R_LARCH_TLS_TPREL32", /* name */
254 false, /* partial_inplace */
255 0, /* src_mask */
256 ALL_ONES, /* dst_mask */
257 false, /* pcrel_offset */
258 BFD_RELOC_LARCH_TLS_TPREL32, /* bfd_reloc_code_real_type */
259 NULL, /* adjust_reloc_bits */
260 NULL), /* larch_reloc_type_name */
261
262 LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64, /* type (11). */
263 0, /* rightshift */
264 8, /* size */
265 64, /* bitsize */
266 false, /* pc_relative */
267 0, /* bitpos */
268 complain_overflow_dont, /* complain_on_overflow */
269 bfd_elf_generic_reloc, /* special_function */
270 "R_LARCH_TLS_TPREL64", /* name */
271 false, /* partial_inplace */
272 0, /* src_mask */
273 ALL_ONES, /* dst_mask */
274 false, /* pcrel_offset */
275 BFD_RELOC_LARCH_TLS_TPREL64, /* bfd_reloc_code_real_type */
276 NULL, /* adjust_reloc_bits */
277 NULL), /* larch_reloc_type_name */
278
279 LOONGARCH_HOWTO (R_LARCH_IRELATIVE, /* type (12). */
280 0, /* rightshift */
281 4, /* size */
282 32, /* bitsize */
283 false, /* pc_relative */
284 0, /* bitpos */
285 complain_overflow_dont, /* complain_on_overflow */
286 bfd_elf_generic_reloc, /* special_function */
287 "R_LARCH_IRELATIVE", /* name */
288 false, /* partial_inplace */
289 0, /* src_mask */
290 ALL_ONES, /* dst_mask */
291 false, /* pcrel_offset */
292 BFD_RELOC_NONE, /* undefined? */
293 NULL, /* adjust_reloc_bits */
294 NULL), /* larch_reloc_type_name */
295
296 LOONGARCH_EMPTY_HOWTO (13),
297 LOONGARCH_EMPTY_HOWTO (14),
298 LOONGARCH_EMPTY_HOWTO (15),
299 LOONGARCH_EMPTY_HOWTO (16),
300 LOONGARCH_EMPTY_HOWTO (17),
301 LOONGARCH_EMPTY_HOWTO (18),
302 LOONGARCH_EMPTY_HOWTO (19),
303
304 LOONGARCH_HOWTO (R_LARCH_MARK_LA, /* type (20). */
305 0, /* rightshift. */
306 0, /* size. */
307 0, /* bitsize. */
308 false, /* pc_relative. */
309 0, /* bitpos. */
310 complain_overflow_signed, /* complain_on_overflow. */
311 bfd_elf_generic_reloc, /* special_function. */
312 "R_LARCH_MARK_LA", /* name. */
313 false, /* partial_inplace. */
314 0, /* src_mask. */
315 0, /* dst_mask. */
316 false, /* pcrel_offset */
317 BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */
318 NULL, /* adjust_reloc_bits */
319 NULL), /* larch_reloc_type_name */
320
321 LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
322 0, /* rightshift. */
323 0, /* size. */
324 0, /* bitsize. */
325 false, /* pc_relative. */
326 0, /* bitpos. */
327 complain_overflow_signed, /* complain_on_overflow. */
328 bfd_elf_generic_reloc, /* special_function. */
329 "R_LARCH_MARK_PCREL", /* name. */
330 false, /* partial_inplace. */
331 0, /* src_mask. */
332 0, /* dst_mask. */
333 false, /* pcrel_offset */
334 BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */
335 NULL, /* adjust_reloc_bits */
336 NULL), /* larch_reloc_type_name */
337
338 LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
339 2, /* rightshift. */
340 4, /* size. */
341 32, /* bitsize. */
342 true /* FIXME: somewhat use this. */, /* pc_relative. */
343 0, /* bitpos. */
344 complain_overflow_signed, /* complain_on_overflow. */
345 bfd_elf_generic_reloc, /* special_function. */
346 "R_LARCH_SOP_PUSH_PCREL", /* name. */
347 false, /* partial_inplace. */
348 0x03ffffff, /* src_mask. */
349 0x03ffffff, /* dst_mask. */
350 false, /* pcrel_offset */
351 BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */
352 NULL, /* adjust_reloc_bits */
353 NULL), /* larch_reloc_type_name */
354
355 /* type 23-37. */
356 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
357 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP),
358 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL),
359 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL),
360 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT),
361 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD),
362 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL),
363 LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT),
364 LOONGARCH_DEFAULT_HOWTO (SOP_NOT),
365 LOONGARCH_DEFAULT_HOWTO (SOP_SUB),
366 LOONGARCH_DEFAULT_HOWTO (SOP_SL),
367 LOONGARCH_DEFAULT_HOWTO (SOP_SR),
368 LOONGARCH_DEFAULT_HOWTO (SOP_ADD),
369 LOONGARCH_DEFAULT_HOWTO (SOP_AND),
370 LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
371
372 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */
373 0, /* rightshift. */
374 4, /* size. */
375 5, /* bitsize. */
376 false, /* pc_relative. */
377 10, /* bitpos. */
378 complain_overflow_signed, /* complain_on_overflow. */
379 bfd_elf_generic_reloc, /* special_function. */
380 "R_LARCH_SOP_POP_32_S_10_5", /* name. */
381 false, /* partial_inplace. */
382 0, /* src_mask */
383 0x7c00, /* dst_mask */
384 false, /* pcrel_offset */
385 BFD_RELOC_LARCH_SOP_POP_32_S_10_5, /* bfd_reloc_code_real_type */
386 reloc_bits, /* adjust_reloc_bits */
387 NULL), /* larch_reloc_type_name */
388
389 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */
390 0, /* rightshift. */
391 4, /* size. */
392 12, /* bitsize. */
393 false, /* pc_relative. */
394 10, /* bitpos. */
395 complain_overflow_unsigned, /* complain_on_overflow. */
396 bfd_elf_generic_reloc, /* special_function. */
397 "R_LARCH_SOP_POP_32_U_10_12", /* name. */
398 false, /* partial_inplace. */
399 0, /* src_mask */
400 0x3ffc00, /* dst_mask */
401 false, /* pcrel_offset */
402 BFD_RELOC_LARCH_SOP_POP_32_U_10_12, /* bfd_reloc_code_real_type */
403 reloc_bits, /* adjust_reloc_bits */
404 NULL), /* larch_reloc_type_name */
405
406 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */
407 0, /* rightshift. */
408 4, /* size. */
409 12, /* bitsize. */
410 false, /* pc_relative. */
411 10, /* bitpos. */
412 complain_overflow_signed, /* complain_on_overflow. */
413 bfd_elf_generic_reloc, /* special_function. */
414 "R_LARCH_SOP_POP_32_S_10_12", /* name. */
415 false, /* partial_inplace. */
416 0, /* src_mask */
417 0x3ffc00, /* dst_mask */
418 false, /* pcrel_offset */
419 BFD_RELOC_LARCH_SOP_POP_32_S_10_12, /* bfd_reloc_code_real_type */
420 reloc_bits, /* adjust_reloc_bits */
421 NULL), /* larch_reloc_type_name */
422
423 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */
424 0, /* rightshift. */
425 4, /* size. */
426 16, /* bitsize. */
427 false, /* pc_relative. */
428 10, /* bitpos. */
429 complain_overflow_signed, /* complain_on_overflow. */
430 bfd_elf_generic_reloc, /* special_function. */
431 "R_LARCH_SOP_POP_32_S_10_16", /* name. */
432 false, /* partial_inplace. */
433 0, /* src_mask */
434 0x3fffc00, /* dst_mask */
435 false, /* pcrel_offset */
436 BFD_RELOC_LARCH_SOP_POP_32_S_10_16, /* bfd_reloc_code_real_type */
437 reloc_bits, /* adjust_reloc_bits */
438 NULL), /* larch_reloc_type_name */
439
440 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */
441 2, /* rightshift. */
442 4, /* size. */
443 16, /* bitsize. */
444 false, /* pc_relative. */
445 10, /* bitpos. */
446 complain_overflow_signed, /* complain_on_overflow. */
447 bfd_elf_generic_reloc, /* special_function. */
448 "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */
449 false, /* partial_inplace. */
450 0, /* src_mask */
451 0x3fffc00, /* dst_mask */
452 false, /* pcrel_offset */
453 BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2, /* bfd_reloc_code_real_type */
454 reloc_sign_bits, /* adjust_reloc_bits */
455 NULL), /* larch_reloc_type_name */
456
457 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */
458 0, /* rightshift. */
459 4, /* size. */
460 20, /* bitsize. */
461 false, /* pc_relative. */
462 5, /* bitpos. */
463 complain_overflow_signed, /* complain_on_overflow. */
464 bfd_elf_generic_reloc, /* special_function. */
465 "R_LARCH_SOP_POP_32_S_5_20", /* name. */
466 false, /* partial_inplace. */
467 0, /* src_mask */
468 0x1ffffe0, /* dst_mask */
469 false, /* pcrel_offset */
470 BFD_RELOC_LARCH_SOP_POP_32_S_5_20, /* bfd_reloc_code_real_type */
471 reloc_bits, /* adjust_reloc_bits */
472 NULL), /* larch_reloc_type_name */
473
474 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
475 /* type (44). */
476 2, /* rightshift. */
477 4, /* size. */
478 21, /* bitsize. */
479 false, /* pc_relative. */
480 0, /* bitpos. */
481 complain_overflow_signed, /* complain_on_overflow. */
482 bfd_elf_generic_reloc, /* special_function. */
483 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */
484 false, /* partial_inplace. */
485 0xfc0003e0, /* src_mask */
486 0xfc0003e0, /* dst_mask */
487 false, /* pcrel_offset */
488 BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
489 /* bfd_reloc_code_real_type */
490 reloc_sign_bits, /* adjust_reloc_bits */
491 NULL), /* larch_reloc_type_name */
492
493 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
494 2, /* rightshift. */
495 4, /* size. */
496 26, /* bitsize. */
497 false, /* pc_relative. */
498 0, /* bitpos. */
499 complain_overflow_signed, /* complain_on_overflow. */
500 bfd_elf_generic_reloc, /* special_function. */
501 "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", /* name. */
502 false, /* partial_inplace. */
503 0, /* src_mask */
504 0x03ffffff, /* dst_mask */
505 false, /* pcrel_offset */
506 BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
507 /* bfd_reloc_code_real_type */
508 reloc_sign_bits, /* adjust_reloc_bits */
509 NULL), /* larch_reloc_type_name */
510
511 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
512 0, /* rightshift. */
513 4, /* size. */
514 32, /* bitsize. */
515 false, /* pc_relative. */
516 0, /* bitpos. */
517 complain_overflow_unsigned, /* complain_on_overflow. */
518 bfd_elf_generic_reloc, /* special_function. */
519 "R_LARCH_SOP_POP_32_S_U", /* name. */
520 false, /* partial_inplace. */
521 0xffffffff00000000, /* src_mask */
522 0x00000000ffffffff, /* dst_mask */
523 false, /* pcrel_offset */
524 BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */
525 reloc_bits, /* adjust_reloc_bits */
526 NULL), /* larch_reloc_type_name */
527
528 /* 8-bit in-place addition, for local label subtraction. */
529 LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
530 0, /* rightshift. */
531 1, /* size. */
532 8, /* bitsize. */
533 false, /* pc_relative. */
534 0, /* bitpos. */
535 complain_overflow_dont, /* complain_on_overflow. */
536 loongarch_elf_add_sub_reloc, /* special_function. */
537 "R_LARCH_ADD8", /* name. */
538 false, /* partial_inplace. */
539 0, /* src_mask. */
540 0xff, /* dst_mask. */
541 false, /* pcrel_offset. */
542 BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type. */
543 NULL, /* adjust_reloc_bits. */
544 NULL), /* larch_reloc_type_name. */
545
546 /* 16-bit in-place addition, for local label subtraction. */
547 LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
548 0, /* rightshift. */
549 2, /* size. */
550 16, /* bitsize. */
551 false, /* pc_relative. */
552 0, /* bitpos. */
553 complain_overflow_dont, /* complain_on_overflow. */
554 loongarch_elf_add_sub_reloc, /* special_function. */
555 "R_LARCH_ADD16", /* name. */
556 false, /* partial_inplace. */
557 0, /* src_mask. */
558 0xffff, /* dst_mask. */
559 false, /* pcrel_offset. */
560 BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type. */
561 NULL, /* adjust_reloc_bits. */
562 NULL), /* larch_reloc_type_name. */
563
564 /* 24-bit in-place addition, for local label subtraction. */
565 LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
566 0, /* rightshift. */
567 3, /* size. */
568 24, /* bitsize. */
569 false, /* pc_relative. */
570 0, /* bitpos. */
571 complain_overflow_dont, /* complain_on_overflow. */
572 loongarch_elf_add_sub_reloc, /* special_function. */
573 "R_LARCH_ADD24", /* name. */
574 false, /* partial_inplace. */
575 0, /* src_mask. */
576 0xffffff, /* dst_mask. */
577 false, /* pcrel_offset. */
578 BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type. */
579 NULL, /* adjust_reloc_bits. */
580 NULL), /* larch_reloc_type_name. */
581
582 /* 32-bit in-place addition, for local label subtraction. */
583 LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
584 0, /* rightshift. */
585 4, /* size. */
586 32, /* bitsize. */
587 false, /* pc_relative. */
588 0, /* bitpos. */
589 complain_overflow_dont, /* complain_on_overflow. */
590 loongarch_elf_add_sub_reloc, /* special_function. */
591 "R_LARCH_ADD32", /* name. */
592 false, /* partial_inplace. */
593 0, /* src_mask. */
594 0xffffffff, /* dst_mask. */
595 false, /* pcrel_offset. */
596 BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type. */
597 NULL, /* adjust_reloc_bits. */
598 NULL), /* larch_reloc_type_name. */
599
600 /* 64-bit in-place addition, for local label subtraction. */
601 LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
602 0, /* rightshift. */
603 8, /* size. */
604 64, /* bitsize. */
605 false, /* pc_relative. */
606 0, /* bitpos. */
607 complain_overflow_dont, /* complain_on_overflow. */
608 loongarch_elf_add_sub_reloc, /* special_function. */
609 "R_LARCH_ADD64", /* name. */
610 false, /* partial_inplace. */
611 0, /* src_mask. */
612 ALL_ONES, /* dst_mask. */
613 false, /* pcrel_offset. */
614 BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type. */
615 NULL, /* adjust_reloc_bits. */
616 NULL), /* larch_reloc_type_name. */
617
618 /* 8-bit in-place subtraction, for local label subtraction. */
619 LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
620 0, /* rightshift. */
621 1, /* size. */
622 8, /* bitsize. */
623 false, /* pc_relative. */
624 0, /* bitpos. */
625 complain_overflow_dont, /* complain_on_overflow. */
626 loongarch_elf_add_sub_reloc, /* special_function. */
627 "R_LARCH_SUB8", /* name. */
628 false, /* partial_inplace. */
629 0, /* src_mask. */
630 0xff, /* dst_mask. */
631 false, /* pcrel_offset. */
632 BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type. */
633 NULL, /* adjust_reloc_bits. */
634 NULL), /* larch_reloc_type_name. */
635
636 /* 16-bit in-place subtraction, for local label subtraction. */
637 LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
638 0, /* rightshift. */
639 2, /* size. */
640 16, /* bitsize. */
641 false, /* pc_relative. */
642 0, /* bitpos. */
643 complain_overflow_dont, /* complain_on_overflow. */
644 loongarch_elf_add_sub_reloc, /* special_function. */
645 "R_LARCH_SUB16", /* name. */
646 false, /* partial_inplace. */
647 0, /* src_mask. */
648 0xffff, /* dst_mask. */
649 false, /* pcrel_offset. */
650 BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type. */
651 NULL, /* adjust_reloc_bits. */
652 NULL), /* larch_reloc_type_name. */
653
654 /* 24-bit in-place subtraction, for local label subtraction. */
655 LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
656 0, /* rightshift. */
657 3, /* size. */
658 24, /* bitsize. */
659 false, /* pc_relative. */
660 0, /* bitpos. */
661 complain_overflow_dont, /* complain_on_overflow. */
662 loongarch_elf_add_sub_reloc, /* special_function. */
663 "R_LARCH_SUB24", /* name. */
664 false, /* partial_inplace. */
665 0, /* src_mask. */
666 0xffffff, /* dst_mask. */
667 false, /* pcrel_offset. */
668 BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type. */
669 NULL, /* adjust_reloc_bits. */
670 NULL), /* larch_reloc_type_name. */
671
672 /* 32-bit in-place subtraction, for local label subtraction. */
673 LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
674 0, /* rightshift. */
675 4, /* size. */
676 32, /* bitsize. */
677 false, /* pc_relative. */
678 0, /* bitpos. */
679 complain_overflow_dont, /* complain_on_overflow. */
680 loongarch_elf_add_sub_reloc, /* special_function. */
681 "R_LARCH_SUB32", /* name. */
682 false, /* partial_inplace. */
683 0, /* src_mask. */
684 0xffffffff, /* dst_mask. */
685 false, /* pcrel_offset. */
686 BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type. */
687 NULL, /* adjust_reloc_bits. */
688 NULL), /* larch_reloc_type_name. */
689
690 /* 64-bit in-place subtraction, for local label subtraction. */
691 LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
692 0, /* rightshift. */
693 8, /* size. */
694 64, /* bitsize. */
695 false, /* pc_relative. */
696 0, /* bitpos. */
697 complain_overflow_dont, /* complain_on_overflow. */
698 loongarch_elf_add_sub_reloc, /* special_function. */
699 "R_LARCH_SUB64", /* name. */
700 false, /* partial_inplace. */
701 0, /* src_mask. */
702 ALL_ONES, /* dst_mask. */
703 false, /* pcrel_offset. */
704 BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type. */
705 NULL, /* adjust_reloc_bits. */
706 NULL), /* larch_reloc_type_name. */
707
708 LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
709 0, /* rightshift. */
710 0, /* size. */
711 0, /* bitsize. */
712 false, /* pc_relative. */
713 0, /* bitpos. */
714 complain_overflow_signed, /* complain_on_overflow. */
715 bfd_elf_generic_reloc, /* special_function. */
716 "R_LARCH_GNU_VTINHERIT", /* name. */
717 false, /* partial_inplace. */
718 0, /* src_mask */
719 0, /* dst_mask */
720 false, /* pcrel_offset */
721 BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
722 NULL, /* adjust_reloc_bits */
723 NULL), /* larch_reloc_type_name */
724
725 LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
726 0, /* rightshift. */
727 0, /* size. */
728 0, /* bitsize. */
729 false, /* pc_relative. */
730 0, /* bitpos. */
731 complain_overflow_signed, /* complain_on_overflow. */
732 NULL, /* special_function. */
733 "R_LARCH_GNU_VTENTRY", /* name. */
734 false, /* partial_inplace. */
735 0, /* src_mask */
736 0, /* dst_mask */
737 false, /* pcrel_offset */
738 BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
739 NULL, /* adjust_reloc_bits */
740 NULL), /* larch_reloc_type_name */
741
742 LOONGARCH_EMPTY_HOWTO (59),
743 LOONGARCH_EMPTY_HOWTO (60),
744 LOONGARCH_EMPTY_HOWTO (61),
745 LOONGARCH_EMPTY_HOWTO (62),
746 LOONGARCH_EMPTY_HOWTO (63),
747
748 /* New reloc types. */
749 LOONGARCH_HOWTO (R_LARCH_B16, /* type (64). */
750 2, /* rightshift. */
751 4, /* size. */
752 16, /* bitsize. */
753 false, /* pc_relative. */
754 10, /* bitpos. */
755 complain_overflow_signed, /* complain_on_overflow. */
756 bfd_elf_generic_reloc, /* special_function. */
757 "R_LARCH_B16", /* name. */
758 false, /* partial_inplace. */
759 0, /* src_mask. */
760 0x3fffc00, /* dst_mask. */
761 false, /* pcrel_offset. */
762 BFD_RELOC_LARCH_B16, /* bfd_reloc_code_real_type. */
763 reloc_sign_bits, /* adjust_reloc_bits. */
764 "b16"), /* larch_reloc_type_name. */
765
766 LOONGARCH_HOWTO (R_LARCH_B21, /* type (65). */
767 2, /* rightshift. */
768 4, /* size. */
769 21, /* bitsize. */
770 false, /* pc_relative. */
771 0, /* bitpos. */
772 complain_overflow_signed, /* complain_on_overflow. */
773 bfd_elf_generic_reloc, /* special_function. */
774 "R_LARCH_B21", /* name. */
775 false, /* partial_inplace. */
776 0, /* src_mask. */
777 0x3fffc1f, /* dst_mask. */
778 false, /* pcrel_offset. */
779 BFD_RELOC_LARCH_B21, /* bfd_reloc_code_real_type. */
780 reloc_sign_bits, /* adjust_reloc_bits. */
781 "b21"), /* larch_reloc_type_name. */
782
783 LOONGARCH_HOWTO (R_LARCH_B26, /* type (66). */
784 2, /* rightshift. */
785 4, /* size. */
786 26, /* bitsize. */
787 false, /* pc_relative. */
788 0, /* bitpos. */
789 complain_overflow_signed, /* complain_on_overflow. */
790 bfd_elf_generic_reloc, /* special_function. */
791 "R_LARCH_B26", /* name. */
792 false, /* partial_inplace. */
793 0, /* src_mask. */
794 0x03ffffff, /* dst_mask. */
795 false, /* pcrel_offset. */
796 BFD_RELOC_LARCH_B26, /* bfd_reloc_code_real_type. */
797 reloc_sign_bits, /* adjust_reloc_bits. */
798 "b26"), /* larch_reloc_type_name. */
799
800 LOONGARCH_HOWTO (R_LARCH_ABS_HI20, /* type (67). */
801 12, /* rightshift. */
802 4, /* size. */
803 20, /* bitsize. */
804 false, /* pc_relative. */
805 5, /* bitpos. */
806 complain_overflow_signed, /* complain_on_overflow. */
807 bfd_elf_generic_reloc, /* special_function. */
808 "R_LARCH_ABS_HI20", /* name. */
809 false, /* partial_inplace. */
810 0, /* src_mask */
811 0x1ffffe0, /* dst_mask */
812 false, /* pcrel_offset */
813 BFD_RELOC_LARCH_ABS_HI20, /* bfd_reloc_code_real_type */
814 reloc_bits, /* adjust_reloc_bits */
815 "abs_hi20"), /* larch_reloc_type_name */
816
817 LOONGARCH_HOWTO (R_LARCH_ABS_LO12, /* type (68). */
818 0, /* rightshift. */
819 4, /* size. */
820 12, /* bitsize. */
821 false, /* pc_relative. */
822 10, /* bitpos. */
823 complain_overflow_unsigned, /* complain_on_overflow. */
824 bfd_elf_generic_reloc, /* special_function. */
825 "R_LARCH_ABS_LO12", /* name. */
826 false, /* partial_inplace. */
827 0, /* src_mask */
828 0x3ffc00, /* dst_mask */
829 false, /* pcrel_offset */
830 BFD_RELOC_LARCH_ABS_LO12, /* bfd_reloc_code_real_type */
831 reloc_bits, /* adjust_reloc_bits */
832 "abs_lo12"), /* larch_reloc_type_name */
833
834 LOONGARCH_HOWTO (R_LARCH_ABS64_LO20, /* type (69). */
835 32, /* rightshift. */
836 4, /* size. */
837 20, /* bitsize. */
838 false, /* pc_relative. */
839 5, /* bitpos. */
840 complain_overflow_signed, /* complain_on_overflow. */
841 bfd_elf_generic_reloc, /* special_function. */
842 "R_LARCH_ABS64_LO20", /* name. */
843 false, /* partial_inplace. */
844 0, /* src_mask */
845 0x1ffffe0, /* dst_mask */
846 false, /* pcrel_offset */
847 BFD_RELOC_LARCH_ABS64_LO20, /* bfd_reloc_code_real_type */
848 reloc_bits, /* adjust_reloc_bits */
849 "abs64_lo20"), /* larch_reloc_type_name */
850
851 LOONGARCH_HOWTO (R_LARCH_ABS64_HI12, /* type (70). */
852 52, /* rightshift. */
853 4, /* size. */
854 12, /* bitsize. */
855 false, /* pc_relative. */
856 10, /* bitpos. */
857 complain_overflow_signed, /* complain_on_overflow. */
858 bfd_elf_generic_reloc, /* special_function. */
859 "R_LARCH_ABS64_HI12", /* name. */
860 false, /* partial_inplace. */
861 0, /* src_mask */
862 0x3ffc00, /* dst_mask */
863 false, /* pcrel_offset */
864 BFD_RELOC_LARCH_ABS64_HI12, /* bfd_reloc_code_real_type */
865 reloc_bits, /* adjust_reloc_bits */
866 "abs64_hi12"), /* larch_reloc_type_name */
867
868 LOONGARCH_HOWTO (R_LARCH_PCALA_HI20, /* type (71). */
869 12, /* rightshift. */
870 4, /* size. */
871 20, /* bitsize. */
872 false, /* pc_relative. */
873 5, /* bitpos. */
874 complain_overflow_signed, /* complain_on_overflow. */
875 bfd_elf_generic_reloc, /* special_function. */
876 "R_LARCH_PCALA_HI20", /* name. */
877 false, /* partial_inplace. */
878 0, /* src_mask */
879 0x1ffffe0, /* dst_mask */
880 false, /* pcrel_offset */
881 BFD_RELOC_LARCH_PCALA_HI20, /* bfd_reloc_code_real_type */
882 reloc_bits, /* adjust_reloc_bits */
883 "pc_hi20"), /* larch_reloc_type_name */
884
885 LOONGARCH_HOWTO (R_LARCH_PCALA_LO12, /* type (72). */
886 0, /* rightshift. */
887 4, /* size. */
888 12, /* bitsize. */
889 false, /* pc_relative. */
890 10, /* bitpos. */
891 complain_overflow_signed, /* complain_on_overflow. */
892 bfd_elf_generic_reloc, /* special_function. */
893 "R_LARCH_PCALA_LO12", /* name. */
894 false, /* partial_inplace. */
895 0, /* src_mask */
896 0x3ffc00, /* dst_mask */
897 false, /* pcrel_offset */
898 BFD_RELOC_LARCH_PCALA_LO12, /* bfd_reloc_code_real_type */
899 reloc_bits, /* adjust_reloc_bits */
900 "pc_lo12"), /* larch_reloc_type_name */
901
902 LOONGARCH_HOWTO (R_LARCH_PCALA64_LO20, /* type (73). */
903 32, /* rightshift. */
904 4, /* size. */
905 20, /* bitsize. */
906 false, /* pc_relative. */
907 5, /* bitpos. */
908 complain_overflow_signed, /* complain_on_overflow. */
909 bfd_elf_generic_reloc, /* special_function. */
910 "R_LARCH_PCALA64_LO20", /* name. */
911 false, /* partial_inplace. */
912 0, /* src_mask */
913 0x1ffffe0, /* dst_mask */
914 false, /* pcrel_offset */
915 BFD_RELOC_LARCH_PCALA64_LO20, /* bfd_reloc_code_real_type */
916 reloc_bits, /* adjust_reloc_bits */
917 "pc64_lo20"), /* larch_reloc_type_name */
918
919 LOONGARCH_HOWTO (R_LARCH_PCALA64_HI12, /* type (74). */
920 52, /* rightshift. */
921 4, /* size. */
922 12, /* bitsize. */
923 false, /* pc_relative. */
924 10, /* bitpos. */
925 complain_overflow_signed, /* complain_on_overflow. */
926 bfd_elf_generic_reloc, /* special_function. */
927 "R_LARCH_PCALA64_HI12", /* name. */
928 false, /* partial_inplace. */
929 0, /* src_mask */
930 0x3ffc00, /* dst_mask */
931 false, /* pcrel_offset */
932 BFD_RELOC_LARCH_PCALA64_HI12, /* bfd_reloc_code_real_type */
933 reloc_bits, /* adjust_reloc_bits */
934 "pc64_hi12"), /* larch_reloc_type_name */
935
936 LOONGARCH_HOWTO (R_LARCH_GOT_PC_HI20, /* type (75). */
937 12, /* rightshift. */
938 4, /* size. */
939 20, /* bitsize. */
940 false, /* pc_relative. */
941 5, /* bitpos. */
942 complain_overflow_signed, /* complain_on_overflow. */
943 bfd_elf_generic_reloc, /* special_function. */
944 "R_LARCH_GOT_PC_HI20", /* name. */
945 false, /* partial_inplace. */
946 0, /* src_mask */
947 0x1ffffe0, /* dst_mask */
948 false, /* pcrel_offset */
949 BFD_RELOC_LARCH_GOT_PC_HI20, /* bfd_reloc_code_real_type */
950 reloc_bits, /* adjust_reloc_bits */
951 "got_pc_hi20"), /* larch_reloc_type_name */
952
953 LOONGARCH_HOWTO (R_LARCH_GOT_PC_LO12, /* type (76). */
954 0, /* rightshift. */
955 4, /* size. */
956 12, /* bitsize. */
957 false, /* pc_relative. */
958 10, /* bitpos. */
959 complain_overflow_signed, /* complain_on_overflow. */
960 bfd_elf_generic_reloc, /* special_function. */
961 "R_LARCH_GOT_PC_LO12", /* name. */
962 false, /* partial_inplace. */
963 0, /* src_mask */
964 0x3ffc00, /* dst_mask */
965 false, /* pcrel_offset */
966 BFD_RELOC_LARCH_GOT_PC_LO12, /* bfd_reloc_code_real_type */
967 reloc_bits, /* adjust_reloc_bits */
968 "got_pc_lo12"), /* larch_reloc_type_name */
969
970 LOONGARCH_HOWTO (R_LARCH_GOT64_PC_LO20, /* type (77). */
971 32, /* rightshift. */
972 4, /* size. */
973 20, /* bitsize. */
974 false, /* pc_relative. */
975 5, /* bitpos. */
976 complain_overflow_signed, /* complain_on_overflow. */
977 bfd_elf_generic_reloc, /* special_function. */
978 "R_LARCH_GOT64_PC_LO20", /* name. */
979 false, /* partial_inplace. */
980 0, /* src_mask */
981 0x1ffffe0, /* dst_mask */
982 false, /* pcrel_offset */
983 BFD_RELOC_LARCH_GOT64_PC_LO20, /* bfd_reloc_code_real_type */
984 reloc_bits, /* adjust_reloc_bits */
985 "got64_pc_lo20"), /* larch_reloc_type_name */
986
987 LOONGARCH_HOWTO (R_LARCH_GOT64_PC_HI12, /* type (78). */
988 52, /* rightshift. */
989 4, /* size. */
990 12, /* bitsize. */
991 false, /* pc_relative. */
992 10, /* bitpos. */
993 complain_overflow_signed, /* complain_on_overflow. */
994 bfd_elf_generic_reloc, /* special_function. */
995 "R_LARCH_GOT64_PC_HI12", /* name. */
996 false, /* partial_inplace. */
997 0, /* src_mask */
998 0x3ffc00, /* dst_mask */
999 false, /* pcrel_offset */
1000 BFD_RELOC_LARCH_GOT64_PC_HI12, /* bfd_reloc_code_real_type */
1001 reloc_bits, /* adjust_reloc_bits */
1002 "got64_pc_hi12"), /* larch_reloc_type_name */
1003
1004 LOONGARCH_HOWTO (R_LARCH_GOT_HI20, /* type (79). */
1005 12, /* rightshift. */
1006 4, /* size. */
1007 20, /* bitsize. */
1008 false, /* pc_relative. */
1009 5, /* bitpos. */
1010 complain_overflow_signed, /* complain_on_overflow. */
1011 bfd_elf_generic_reloc, /* special_function. */
1012 "R_LARCH_GOT_HI20", /* name. */
1013 false, /* partial_inplace. */
1014 0, /* src_mask */
1015 0x1ffffe0, /* dst_mask */
1016 false, /* pcrel_offset */
1017 BFD_RELOC_LARCH_GOT_HI20, /* bfd_reloc_code_real_type */
1018 reloc_bits, /* adjust_reloc_bits */
1019 "got_hi20"), /* larch_reloc_type_name */
1020
1021 LOONGARCH_HOWTO (R_LARCH_GOT_LO12, /* type (80). */
1022 0, /* rightshift. */
1023 4, /* size. */
1024 12, /* bitsize. */
1025 false, /* pc_relative. */
1026 10, /* bitpos. */
1027 complain_overflow_signed, /* complain_on_overflow. */
1028 bfd_elf_generic_reloc, /* special_function. */
1029 "R_LARCH_GOT_LO12", /* name. */
1030 false, /* partial_inplace. */
1031 0, /* src_mask */
1032 0x3ffc00, /* dst_mask */
1033 false, /* pcrel_offset */
1034 BFD_RELOC_LARCH_GOT_LO12, /* bfd_reloc_code_real_type */
1035 reloc_bits, /* adjust_reloc_bits */
1036 "got_lo12"), /* larch_reloc_type_name */
1037
1038 LOONGARCH_HOWTO (R_LARCH_GOT64_LO20, /* type (81). */
1039 32, /* rightshift. */
1040 4, /* size. */
1041 20, /* bitsize. */
1042 false, /* pc_relative. */
1043 5, /* bitpos. */
1044 complain_overflow_signed, /* complain_on_overflow. */
1045 bfd_elf_generic_reloc, /* special_function. */
1046 "R_LARCH_GOT64_LO20", /* name. */
1047 false, /* partial_inplace. */
1048 0, /* src_mask */
1049 0x1ffffe0, /* dst_mask */
1050 false, /* pcrel_offset */
1051 BFD_RELOC_LARCH_GOT64_LO20, /* bfd_reloc_code_real_type */
1052 reloc_bits, /* adjust_reloc_bits */
1053 "got64_lo20"), /* larch_reloc_type_name */
1054
1055 LOONGARCH_HOWTO (R_LARCH_GOT64_HI12, /* type (82). */
1056 52, /* rightshift. */
1057 4, /* size. */
1058 12, /* bitsize. */
1059 false, /* pc_relative. */
1060 10, /* bitpos. */
1061 complain_overflow_signed, /* complain_on_overflow. */
1062 bfd_elf_generic_reloc, /* special_function. */
1063 "R_LARCH_GOT64_HI12", /* name. */
1064 false, /* partial_inplace. */
1065 0, /* src_mask */
1066 0x3ffc00, /* dst_mask */
1067 false, /* pcrel_offset */
1068 BFD_RELOC_LARCH_GOT64_HI12, /* bfd_reloc_code_real_type */
1069 reloc_bits, /* adjust_reloc_bits */
1070 "got64_hi12"), /* larch_reloc_type_name */
1071
1072 LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20, /* type (83). */
1073 12, /* rightshift. */
1074 4, /* size. */
1075 20, /* bitsize. */
1076 false, /* pc_relative. */
1077 5, /* bitpos. */
1078 complain_overflow_signed, /* complain_on_overflow. */
1079 bfd_elf_generic_reloc, /* special_function. */
1080 "R_LARCH_TLS_LE_HI20", /* name. */
1081 false, /* partial_inplace. */
1082 0, /* src_mask */
1083 0x1ffffe0, /* dst_mask */
1084 false, /* pcrel_offset */
1085 BFD_RELOC_LARCH_TLS_LE_HI20, /* bfd_reloc_code_real_type */
1086 reloc_bits, /* adjust_reloc_bits */
1087 "le_hi20"), /* larch_reloc_type_name */
1088
1089 LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12, /* type (84). */
1090 0, /* rightshift. */
1091 4, /* size. */
1092 12, /* bitsize. */
1093 false, /* pc_relative. */
1094 10, /* bitpos. */
1095 complain_overflow_unsigned, /* complain_on_overflow. */
1096 bfd_elf_generic_reloc, /* special_function. */
1097 "R_LARCH_TLS_LE_LO12", /* name. */
1098 false, /* partial_inplace. */
1099 0, /* src_mask */
1100 0x3ffc00, /* dst_mask */
1101 false, /* pcrel_offset */
1102 BFD_RELOC_LARCH_TLS_LE_LO12, /* bfd_reloc_code_real_type */
1103 reloc_bits, /* adjust_reloc_bits */
1104 "le_lo12"), /* larch_reloc_type_name */
1105
1106 LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20, /* type (85). */
1107 32, /* rightshift. */
1108 4, /* size. */
1109 20, /* bitsize. */
1110 false, /* pc_relative. */
1111 5, /* bitpos. */
1112 complain_overflow_signed, /* complain_on_overflow. */
1113 bfd_elf_generic_reloc, /* special_function. */
1114 "R_LARCH_TLS_LE64_LO20", /* name. */
1115 false, /* partial_inplace. */
1116 0, /* src_mask */
1117 0x1ffffe0, /* dst_mask */
1118 false, /* pcrel_offset */
1119 BFD_RELOC_LARCH_TLS_LE64_LO20, /* bfd_reloc_code_real_type */
1120 reloc_bits, /* adjust_reloc_bits */
1121 "le64_lo20"), /* larch_reloc_type_name */
1122
1123 LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12, /* type (86). */
1124 52, /* rightshift. */
1125 4, /* size. */
1126 12, /* bitsize. */
1127 false, /* pc_relative. */
1128 10, /* bitpos. */
1129 complain_overflow_signed, /* complain_on_overflow. */
1130 bfd_elf_generic_reloc, /* special_function. */
1131 "R_LARCH_TLS_LE64_HI12", /* name. */
1132 false, /* partial_inplace. */
1133 0, /* src_mask */
1134 0x3ffc00, /* dst_mask */
1135 false, /* pcrel_offset */
1136 BFD_RELOC_LARCH_TLS_LE64_HI12, /* bfd_reloc_code_real_type */
1137 reloc_bits, /* adjust_reloc_bits */
1138 "le64_hi12"), /* larch_reloc_type_name */
1139
1140 LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20, /* type (87). */
1141 12, /* rightshift. */
1142 4, /* size. */
1143 20, /* bitsize. */
1144 false, /* pc_relative. */
1145 5, /* bitpos. */
1146 complain_overflow_signed, /* complain_on_overflow. */
1147 bfd_elf_generic_reloc, /* special_function. */
1148 "R_LARCH_TLS_IE_PC_HI20", /* name. */
1149 false, /* partial_inplace. */
1150 0, /* src_mask */
1151 0x1ffffe0, /* dst_mask */
1152 false, /* pcrel_offset */
1153 BFD_RELOC_LARCH_TLS_IE_PC_HI20, /* bfd_reloc_code_real_type */
1154 reloc_bits, /* adjust_reloc_bits */
1155 "ie_pc_hi20"), /* larch_reloc_type_name */
1156
1157 LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12, /* type (88). */
1158 0, /* rightshift. */
1159 4, /* size. */
1160 12, /* bitsize. */
1161 false, /* pc_relative. */
1162 10, /* bitpos. */
1163 complain_overflow_signed, /* complain_on_overflow. */
1164 bfd_elf_generic_reloc, /* special_function. */
1165 "R_LARCH_TLS_IE_PC_LO12", /* name. */
1166 false, /* partial_inplace. */
1167 0, /* src_mask */
1168 0x3ffc00, /* dst_mask */
1169 false, /* pcrel_offset */
1170 BFD_RELOC_LARCH_TLS_IE_PC_LO12, /* bfd_reloc_code_real_type */
1171 reloc_bits, /* adjust_reloc_bits */
1172 "ie_pc_lo12"), /* larch_reloc_type_name */
1173
1174 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20, /* type (89). */
1175 32, /* rightshift. */
1176 4, /* size. */
1177 20, /* bitsize. */
1178 false, /* pc_relative. */
1179 5, /* bitpos. */
1180 complain_overflow_signed, /* complain_on_overflow. */
1181 bfd_elf_generic_reloc, /* special_function. */
1182 "R_LARCH_TLS_IE64_PC_LO20", /* name. */
1183 false, /* partial_inplace. */
1184 0, /* src_mask */
1185 0x1ffffe0, /* dst_mask */
1186 false, /* pcrel_offset */
1187 BFD_RELOC_LARCH_TLS_IE64_PC_LO20, /* bfd_reloc_code_real_type */
1188 reloc_bits, /* adjust_reloc_bits */
1189 "ie64_pc_lo20"), /* larch_reloc_type_name */
1190
1191 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12, /* type (90). */
1192 52, /* rightshift. */
1193 4, /* size. */
1194 12, /* bitsize. */
1195 false, /* pc_relative. */
1196 10, /* bitpos. */
1197 complain_overflow_signed, /* complain_on_overflow. */
1198 bfd_elf_generic_reloc, /* special_function. */
1199 "R_LARCH_TLS_IE64_PC_HI12", /* name. */
1200 false, /* partial_inplace. */
1201 0, /* src_mask */
1202 0x3ffc00, /* dst_mask */
1203 false, /* pcrel_offset */
1204 BFD_RELOC_LARCH_TLS_IE64_PC_HI12, /* bfd_reloc_code_real_type */
1205 reloc_bits, /* adjust_reloc_bits */
1206 "ie64_pc_hi12"), /* larch_reloc_type_name */
1207
1208 LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20, /* type (91). */
1209 12, /* rightshift. */
1210 4, /* size. */
1211 20, /* bitsize. */
1212 false, /* pc_relative. */
1213 5, /* bitpos. */
1214 complain_overflow_signed, /* complain_on_overflow. */
1215 bfd_elf_generic_reloc, /* special_function. */
1216 "R_LARCH_TLS_IE_HI20", /* name. */
1217 false, /* partial_inplace. */
1218 0, /* src_mask */
1219 0x1ffffe0, /* dst_mask */
1220 false, /* pcrel_offset */
1221 BFD_RELOC_LARCH_TLS_IE_HI20, /* bfd_reloc_code_real_type */
1222 reloc_bits, /* adjust_reloc_bits */
1223 "ie_hi20"), /* larch_reloc_type_name */
1224
1225 LOONGARCH_HOWTO (R_LARCH_TLS_IE_LO12, /* type (92). */
1226 0, /* rightshift. */
1227 4, /* size. */
1228 12, /* bitsize. */
1229 false, /* pc_relative. */
1230 10, /* bitpos. */
1231 complain_overflow_signed, /* complain_on_overflow. */
1232 bfd_elf_generic_reloc, /* special_function. */
1233 "R_LARCH_TLS_IE_LO12", /* name. */
1234 false, /* partial_inplace. */
1235 0, /* src_mask */
1236 0x3ffc00, /* dst_mask */
1237 false, /* pcrel_offset */
1238 BFD_RELOC_LARCH_TLS_IE_LO12, /* bfd_reloc_code_real_type */
1239 reloc_bits, /* adjust_reloc_bits */
1240 "ie_lo12"), /* larch_reloc_type_name */
1241
1242 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20, /* type (93). */
1243 32, /* rightshift. */
1244 4, /* size. */
1245 20, /* bitsize. */
1246 false, /* pc_relative. */
1247 5, /* bitpos. */
1248 complain_overflow_signed, /* complain_on_overflow. */
1249 bfd_elf_generic_reloc, /* special_function. */
1250 "R_LARCH_TLS_IE64_LO20", /* name. */
1251 false, /* partial_inplace. */
1252 0, /* src_mask */
1253 0x1ffffe0, /* dst_mask */
1254 false, /* pcrel_offset */
1255 BFD_RELOC_LARCH_TLS_IE64_LO20, /* bfd_reloc_code_real_type */
1256 reloc_bits, /* adjust_reloc_bits */
1257 "ie64_lo20"), /* larch_reloc_type_name */
1258
1259 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12, /* type (94). */
1260 52, /* rightshift. */
1261 4, /* size. */
1262 12, /* bitsize. */
1263 false, /* pc_relative. */
1264 10, /* bitpos. */
1265 complain_overflow_signed, /* complain_on_overflow. */
1266 bfd_elf_generic_reloc, /* special_function. */
1267 "R_LARCH_TLS_IE64_HI12", /* name. */
1268 false, /* partial_inplace. */
1269 0, /* src_mask */
1270 0x3ffc00, /* dst_mask */
1271 false, /* pcrel_offset */
1272 BFD_RELOC_LARCH_TLS_IE64_HI12, /* bfd_reloc_code_real_type */
1273 reloc_bits, /* adjust_reloc_bits */
1274 "ie64_hi12"), /* larch_reloc_type_name */
1275
1276 LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20, /* type (95). */
1277 12, /* rightshift. */
1278 4, /* size. */
1279 20, /* bitsize. */
1280 false, /* pc_relative. */
1281 5, /* bitpos. */
1282 complain_overflow_signed, /* complain_on_overflow. */
1283 bfd_elf_generic_reloc, /* special_function. */
1284 "R_LARCH_TLS_LD_PC_HI20", /* name. */
1285 false, /* partial_inplace. */
1286 0, /* src_mask */
1287 0x1ffffe0, /* dst_mask */
1288 false, /* pcrel_offset */
1289 BFD_RELOC_LARCH_TLS_LD_PC_HI20, /* bfd_reloc_code_real_type */
1290 reloc_bits, /* adjust_reloc_bits */
1291 "ld_pc_hi20"), /* larch_reloc_type_name */
1292
1293 LOONGARCH_HOWTO (R_LARCH_TLS_LD_HI20, /* type (96). */
1294 12, /* rightshift. */
1295 4, /* size. */
1296 20, /* bitsize. */
1297 false, /* pc_relative. */
1298 5, /* bitpos. */
1299 complain_overflow_signed, /* complain_on_overflow. */
1300 bfd_elf_generic_reloc, /* special_function. */
1301 "R_LARCH_TLS_LD_HI20", /* name. */
1302 false, /* partial_inplace. */
1303 0, /* src_mask */
1304 0x1ffffe0, /* dst_mask */
1305 false, /* pcrel_offset */
1306 BFD_RELOC_LARCH_TLS_LD_HI20, /* bfd_reloc_code_real_type */
1307 reloc_bits, /* adjust_reloc_bits */
1308 "ld_hi20"), /* larch_reloc_type_name */
1309
1310 LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20, /* type (97). */
1311 12, /* rightshift. */
1312 4, /* size. */
1313 20, /* bitsize. */
1314 false, /* pc_relative. */
1315 5, /* bitpos. */
1316 complain_overflow_signed, /* complain_on_overflow. */
1317 bfd_elf_generic_reloc, /* special_function. */
1318 "R_LARCH_TLS_GD_PC_HI20", /* name. */
1319 false, /* partial_inplace. */
1320 0, /* src_mask */
1321 0x1ffffe0, /* dst_mask */
1322 false, /* pcrel_offset */
1323 BFD_RELOC_LARCH_TLS_GD_PC_HI20, /* bfd_reloc_code_real_type */
1324 reloc_bits, /* adjust_reloc_bits */
1325 "gd_pc_hi20"), /* larch_reloc_type_name */
1326
1327 LOONGARCH_HOWTO (R_LARCH_TLS_GD_HI20, /* type (98). */
1328 12, /* rightshift. */
1329 4, /* size. */
1330 20, /* bitsize. */
1331 false, /* pc_relative. */
1332 5, /* bitpos. */
1333 complain_overflow_signed, /* complain_on_overflow. */
1334 bfd_elf_generic_reloc, /* special_function. */
1335 "R_LARCH_TLS_GD_HI20", /* name. */
1336 false, /* partial_inplace. */
1337 0, /* src_mask */
1338 0x1ffffe0, /* dst_mask */
1339 false, /* pcrel_offset */
1340 BFD_RELOC_LARCH_TLS_GD_HI20, /* bfd_reloc_code_real_type */
1341 reloc_bits, /* adjust_reloc_bits */
1342 "gd_hi20"), /* larch_reloc_type_name */
1343
1344 /* 32-bit PC relative. */
1345 LOONGARCH_HOWTO (R_LARCH_32_PCREL, /* type (99). */
1346 0, /* rightshift. */
1347 4, /* size. */
1348 32, /* bitsize. */
1349 true, /* pc_relative. */
1350 0, /* bitpos. */
1351 complain_overflow_signed, /* complain_on_overflow. */
1352 bfd_elf_generic_reloc, /* special_function. */
1353 "R_LARCH_32_PCREL", /* name. */
1354 false, /* partial_inplace. */
1355 0, /* src_mask */
1356 0xffffffff, /* dst_mask */
1357 false, /* pcrel_offset */
1358 BFD_RELOC_LARCH_32_PCREL, /* bfd_reloc_code_real_type */
1359 NULL, /* adjust_reloc_bits */
1360 NULL), /* larch_reloc_type_name */
1361
1362 /* The paired relocation may be relaxed. */
1363 LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (100). */
1364 0, /* rightshift */
1365 1, /* size */
1366 0, /* bitsize */
1367 false, /* pc_relative */
1368 0, /* bitpos */
1369 complain_overflow_dont, /* complain_on_overflow */
1370 bfd_elf_generic_reloc, /* special_function */
1371 "R_LARCH_RELAX", /* name */
1372 false, /* partial_inplace */
1373 0, /* src_mask */
1374 0, /* dst_mask */
1375 false, /* pcrel_offset */
1376 BFD_RELOC_LARCH_RELAX, /* bfd_reloc_code_real_type */
1377 NULL, /* adjust_reloc_bits */
1378 NULL), /* larch_reloc_type_name */
1379
1380 /* Delete relaxed instruction. */
1381 LOONGARCH_HOWTO (R_LARCH_DELETE, /* type (101). */
1382 0, /* rightshift. */
1383 0, /* size. */
1384 0, /* bitsize. */
1385 false, /* pc_relative. */
1386 0, /* bitpos. */
1387 complain_overflow_dont, /* complain_on_overflow. */
1388 bfd_elf_generic_reloc, /* special_function. */
1389 "R_LARCH_DELETE", /* name. */
1390 false, /* partial_inplace. */
1391 0, /* src_mask. */
1392 0, /* dst_mask. */
1393 false, /* pcrel_offset. */
1394 BFD_RELOC_LARCH_DELETE, /* bfd_reloc_code_real_type. */
1395 NULL, /* adjust_reloc_bits. */
1396 NULL), /* larch_reloc_type_name. */
1397
1398 /* Indicates an alignment statement. The addend field encodes how many
1399 bytes of NOPs follow the statement. The desired alignment is the
1400 addend rounded up to the next power of two. */
1401 LOONGARCH_HOWTO (R_LARCH_ALIGN, /* type (102). */
1402 0, /* rightshift. */
1403 0, /* size. */
1404 0, /* bitsize. */
1405 false, /* pc_relative. */
1406 0, /* bitpos. */
1407 complain_overflow_dont, /* complain_on_overflow. */
1408 bfd_elf_generic_reloc, /* special_function. */
1409 "R_LARCH_ALIGN", /* name. */
1410 false, /* partial_inplace. */
1411 0, /* src_mask. */
1412 0, /* dst_mask. */
1413 false, /* pcrel_offset. */
1414 BFD_RELOC_LARCH_ALIGN, /* bfd_reloc_code_real_type. */
1415 NULL, /* adjust_reloc_bits. */
1416 NULL), /* larch_reloc_type_name. */
1417
1418 /* pcala_hi20 + pcala_lo12 relaxed to pcrel20_s2. */
1419 LOONGARCH_HOWTO (R_LARCH_PCREL20_S2, /* type (103). */
1420 2, /* rightshift. */
1421 4, /* size. */
1422 20, /* bitsize. */
1423 false, /* pc_relative. */
1424 5, /* bitpos. */
1425 complain_overflow_signed, /* complain_on_overflow. */
1426 bfd_elf_generic_reloc, /* special_function. */
1427 "R_LARCH_PCREL20_S2", /* name. */
1428 false, /* partial_inplace. */
1429 0, /* src_mask. */
1430 0x1ffffe0, /* dst_mask. */
1431 false, /* pcrel_offset. */
1432 BFD_RELOC_LARCH_PCREL20_S2, /* bfd_reloc_code_real_type. */
1433 reloc_sign_bits, /* adjust_reloc_bits. */
1434 NULL), /* larch_reloc_type_name. */
1435
1436 /* Canonical Frame Address. */
1437 LOONGARCH_HOWTO (R_LARCH_CFA, /* type (104). */
1438 0, /* rightshift. */
1439 0, /* size. */
1440 0, /* bitsize. */
1441 false, /* pc_relative. */
1442 0, /* bitpos. */
1443 complain_overflow_dont, /* complain_on_overflow. */
1444 bfd_elf_generic_reloc, /* special_function. */
1445 "R_LARCH_CFA", /* name. */
1446 false, /* partial_inplace. */
1447 0, /* src_mask. */
1448 0, /* dst_mask. */
1449 false, /* pcrel_offset. */
1450 BFD_RELOC_LARCH_CFA, /* bfd_reloc_code_real_type. */
1451 NULL, /* adjust_reloc_bits. */
1452 NULL), /* larch_reloc_type_name. */
1453
1454 /* 6-bit in-place addition, for local label subtraction
1455 to calculate DW_CFA_advance_loc. */
1456 LOONGARCH_HOWTO (R_LARCH_ADD6, /* type (105). */
1457 0, /* rightshift. */
1458 1, /* size. */
1459 8, /* bitsize. */
1460 false, /* pc_relative. */
1461 0, /* bitpos. */
1462 complain_overflow_dont, /* complain_on_overflow. */
1463 loongarch_elf_add_sub_reloc, /* special_function. */
1464 "R_LARCH_ADD6", /* name. */
1465 false, /* partial_inplace. */
1466 0, /* src_mask. */
1467 0x3f, /* dst_mask. */
1468 false, /* pcrel_offset. */
1469 BFD_RELOC_LARCH_ADD6, /* bfd_reloc_code_real_type. */
1470 reloc_bits, /* adjust_reloc_bits. */
1471 NULL), /* larch_reloc_type_name. */
1472
1473 /* 6-bit in-place subtraction, for local label subtraction
1474 to calculate DW_CFA_advance_loc. */
1475 LOONGARCH_HOWTO (R_LARCH_SUB6, /* type (106). */
1476 0, /* rightshift. */
1477 1, /* size. */
1478 8, /* bitsize. */
1479 false, /* pc_relative. */
1480 0, /* bitpos. */
1481 complain_overflow_dont, /* complain_on_overflow. */
1482 loongarch_elf_add_sub_reloc, /* special_function. */
1483 "R_LARCH_SUB6", /* name. */
1484 false, /* partial_inplace. */
1485 0, /* src_mask. */
1486 0x3f, /* dst_mask. */
1487 false, /* pcrel_offset. */
1488 BFD_RELOC_LARCH_SUB6, /* bfd_reloc_code_real_type. */
1489 reloc_bits, /* adjust_reloc_bits. */
1490 NULL), /* larch_reloc_type_name. */
1491
1492 /* The length of unsigned-leb128 is variable, just assume the
1493 size is one byte here.
1494 uleb128 in-place addition, for local label subtraction. */
1495 LOONGARCH_HOWTO (R_LARCH_ADD_ULEB128, /* type (107). */
1496 0, /* rightshift. */
1497 1, /* size. */
1498 0, /* bitsize. */
1499 false, /* pc_relative. */
1500 0, /* bitpos. */
1501 complain_overflow_dont, /* complain_on_overflow. */
1502 loongarch_elf_add_sub_reloc_uleb128, /* special_function. */
1503 "R_LARCH_ADD_ULEB128", /* name. */
1504 false, /* partial_inplace. */
1505 0, /* src_mask. */
1506 0, /* dst_mask. */
1507 false, /* pcrel_offset. */
1508 BFD_RELOC_LARCH_ADD_ULEB128, /* bfd_reloc_code_real_type. */
1509 NULL, /* adjust_reloc_bits. */
1510 NULL), /* larch_reloc_type_name. */
1511
1512 /* The length of unsigned-leb128 is variable, just assume the
1513 size is one byte here.
1514 uleb128 in-place subtraction, for local label subtraction. */
1515 LOONGARCH_HOWTO (R_LARCH_SUB_ULEB128, /* type (108). */
1516 0, /* rightshift. */
1517 1, /* size. */
1518 0, /* bitsize. */
1519 false, /* pc_relative. */
1520 0, /* bitpos. */
1521 complain_overflow_dont, /* complain_on_overflow. */
1522 loongarch_elf_add_sub_reloc_uleb128, /* special_function. */
1523 "R_LARCH_SUB_ULEB128", /* name. */
1524 false, /* partial_inplace. */
1525 0, /* src_mask. */
1526 0, /* dst_mask. */
1527 false, /* pcrel_offset. */
1528 BFD_RELOC_LARCH_SUB_ULEB128, /* bfd_reloc_code_real_type. */
1529 NULL, /* adjust_reloc_bits. */
1530 NULL), /* larch_reloc_type_name. */
1531
1532 /* 64-bit PC relative. */
1533 LOONGARCH_HOWTO (R_LARCH_64_PCREL, /* type (109). */
1534 0, /* rightshift. */
1535 8, /* size. */
1536 64, /* bitsize. */
1537 true, /* pc_relative. */
1538 0, /* bitpos. */
1539 complain_overflow_signed, /* complain_on_overflow. */
1540 bfd_elf_generic_reloc, /* special_function. */
1541 "R_LARCH_64_PCREL", /* name. */
1542 false, /* partial_inplace. */
1543 0, /* src_mask */
1544 0xffffffffffffffff, /* dst_mask */
1545 false, /* pcrel_offset */
1546 BFD_RELOC_LARCH_64_PCREL, /* bfd_reloc_code_real_type */
1547 NULL, /* adjust_reloc_bits */
1548 NULL), /* larch_reloc_type_name */
1549
1550 };
1551
1552 reloc_howto_type *
1553 loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
1554 {
1555 if(r_type < R_LARCH_count)
1556 {
1557 /* For search table fast. */
1558 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
1559
1560 if (loongarch_howto_table[r_type].howto.type == r_type)
1561 return (reloc_howto_type *)&loongarch_howto_table[r_type];
1562
1563 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1564 if (loongarch_howto_table[i].howto.type == r_type)
1565 return (reloc_howto_type *)&loongarch_howto_table[i];
1566 }
1567
1568 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1569 abfd, r_type);
1570 bfd_set_error (bfd_error_bad_value);
1571 return NULL;
1572 }
1573
1574 reloc_howto_type *
1575 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
1576 {
1577 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
1578
1579 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1580 if (loongarch_howto_table[i].howto.name
1581 && strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0)
1582 return (reloc_howto_type *)&loongarch_howto_table[i];
1583
1584 (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"),
1585 abfd, r_name);
1586 bfd_set_error (bfd_error_bad_value);
1587
1588 return NULL;
1589 }
1590
1591 /* Cost so much. */
1592 reloc_howto_type *
1593 loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1594 bfd_reloc_code_real_type code)
1595 {
1596 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
1597
1598 /* Fast search for new reloc types. */
1599 if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
1600 {
1601 BFD_ASSERT (BFD_RELOC_LARCH_RELAX - BFD_RELOC_LARCH_B16
1602 == R_LARCH_RELAX - R_LARCH_B16);
1603 loongarch_reloc_howto_type *ht = NULL;
1604 ht = &loongarch_howto_table[code - BFD_RELOC_LARCH_B16 + R_LARCH_B16];
1605 BFD_ASSERT (ht->bfd_type == code);
1606 return (reloc_howto_type *)ht;
1607 }
1608
1609 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1610 if (loongarch_howto_table[i].bfd_type == code)
1611 return (reloc_howto_type *)&loongarch_howto_table[i];
1612
1613 (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"),
1614 abfd, code);
1615 bfd_set_error (bfd_error_bad_value);
1616
1617 return NULL;
1618 }
1619
1620 bfd_reloc_code_real_type
1621 loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1622 const char *l_r_name)
1623 {
1624 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1625 {
1626 loongarch_reloc_howto_type *lht = &loongarch_howto_table[i];
1627 if ((NULL != lht->larch_reloc_type_name)
1628 && (0 == strcmp (lht->larch_reloc_type_name, l_r_name)))
1629 return lht->bfd_type;
1630 }
1631
1632 (*_bfd_error_handler) (_("%pB: unsupported relocation type name %s"),
1633 abfd, l_r_name);
1634 bfd_set_error (bfd_error_bad_value);
1635 return BFD_RELOC_NONE;
1636 }
1637
1638
1639 /* Functions for reloc bits field.
1640 1. Signed extend *fix_val.
1641 2. Return false if overflow. */
1642
1643 #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
1644 (~((((bfd_vma)0x1) << (bitsize)) - 1))
1645
1646 /* Adjust val to perform insn
1647 BFD_RELOC_LARCH_SOP_POP_32_S_10_5
1648 BFD_RELOC_LARCH_SOP_POP_32_S_10_12
1649 BFD_RELOC_LARCH_SOP_POP_32_U_10_12
1650 BFD_RELOC_LARCH_SOP_POP_32_S_10_16
1651 BFD_RELOC_LARCH_SOP_POP_32_S_5_20
1652 BFD_RELOC_LARCH_SOP_POP_32_U. */
1653
1654 static bool
1655 reloc_bits (bfd *abfd ATTRIBUTE_UNUSED,
1656 reloc_howto_type *howto,
1657 bfd_vma *fix_val)
1658 {
1659 bfd_signed_vma val = (bfd_signed_vma)(*fix_val);
1660 bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
1661
1662 val = val >> howto->rightshift;
1663
1664 /* Perform insn bits field. */
1665 val = val & mask;
1666 val <<= howto->bitpos;
1667
1668 *fix_val = (bfd_vma)val;
1669
1670 return true;
1671 }
1672
1673 static bool
1674 reloc_sign_bits (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val)
1675 {
1676 if (howto->complain_on_overflow != complain_overflow_signed)
1677 return false;
1678
1679 bfd_signed_vma val = (bfd_signed_vma)(*fix_val);
1680
1681 /* Check alignment. FIXME: if rightshift is not alingment. */
1682 if (howto->rightshift
1683 && (val & ((((bfd_signed_vma) 1) << howto->rightshift) - 1)))
1684 {
1685 (*_bfd_error_handler) (_("%pB: relocation %s right shift %d error 0x%lx"),
1686 abfd, howto->name, howto->rightshift, (long) val);
1687 bfd_set_error (bfd_error_bad_value);
1688 return false;
1689 }
1690
1691 bfd_signed_vma mask = ((bfd_signed_vma)0x1 << (howto->bitsize
1692 + howto->rightshift - 1)) - 1;
1693
1694 /* Positive number: high part is all 0;
1695 Negative number: if high part is not all 0, high part must be all 1.
1696 high part: from sign bit to highest bit. */
1697 if ((val & ~mask) && ((val & ~mask) != ~mask))
1698 {
1699 (*_bfd_error_handler) (_("%pB: relocation %s overflow 0x%lx"),
1700 abfd, howto->name, (long) val);
1701 bfd_set_error (bfd_error_bad_value);
1702 return false;
1703 }
1704
1705 val = val >> howto->rightshift;
1706 /* can delete? */
1707 mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
1708 val = val & mask;
1709
1710 switch (howto->type)
1711 {
1712 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1713 case R_LARCH_B26:
1714 /* Perform insn bits field. 25:16>>16, 15:0<<10. */
1715 val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
1716 break;
1717 case R_LARCH_B21:
1718 val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
1719 break;
1720 default:
1721 val <<= howto->bitpos;
1722 break;
1723 }
1724
1725 *fix_val = val;
1726 return true;
1727 }
1728
1729 bool
1730 loongarch_adjust_reloc_bitsfield (bfd *abfd, reloc_howto_type *howto,
1731 bfd_vma *fix_val)
1732 {
1733 BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
1734 return ((loongarch_reloc_howto_type *)
1735 howto)->adjust_reloc_bits (abfd, howto, fix_val);
1736 }
1737
1738 static bfd_reloc_status_type
1739 loongarch_elf_add_sub_reloc (bfd *abfd,
1740 arelent *reloc_entry,
1741 asymbol *symbol,
1742 void *data,
1743 asection *input_section,
1744 bfd *output_bfd,
1745 char **error_message ATTRIBUTE_UNUSED)
1746 {
1747 reloc_howto_type *howto = reloc_entry->howto;
1748 bfd_vma relocation;
1749
1750 if (output_bfd != NULL
1751 && (symbol->flags & BSF_SECTION_SYM) == 0
1752 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1753 {
1754 reloc_entry->address += input_section->output_offset;
1755 return bfd_reloc_ok;
1756 }
1757
1758 if (output_bfd != NULL)
1759 return bfd_reloc_continue;
1760
1761 relocation = symbol->value + symbol->section->output_section->vma
1762 + symbol->section->output_offset + reloc_entry->addend;
1763
1764 bfd_size_type octets = reloc_entry->address
1765 * bfd_octets_per_byte (abfd, input_section);
1766 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1767 input_section, octets))
1768 return bfd_reloc_outofrange;
1769
1770 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1771 data + reloc_entry->address);
1772
1773 switch (howto->type)
1774 {
1775 case R_LARCH_ADD6:
1776 case R_LARCH_ADD8:
1777 case R_LARCH_ADD16:
1778 case R_LARCH_ADD32:
1779 case R_LARCH_ADD64:
1780 relocation = old_value + relocation;
1781 break;
1782
1783 case R_LARCH_SUB6:
1784 case R_LARCH_SUB8:
1785 case R_LARCH_SUB16:
1786 case R_LARCH_SUB32:
1787 case R_LARCH_SUB64:
1788 relocation = old_value - relocation;
1789 break;
1790 }
1791
1792 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1793
1794 return bfd_reloc_ok;
1795 }
1796
1797 static bfd_reloc_status_type
1798 loongarch_elf_add_sub_reloc_uleb128 (bfd *abfd,
1799 arelent *reloc_entry,
1800 asymbol *symbol,
1801 void *data,
1802 asection *input_section,
1803 bfd *output_bfd,
1804 char **error_message ATTRIBUTE_UNUSED)
1805 {
1806 reloc_howto_type *howto = reloc_entry->howto;
1807 bfd_vma relocation;
1808
1809 if (output_bfd != NULL
1810 && (symbol->flags & BSF_SECTION_SYM) == 0
1811 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
1812 {
1813 reloc_entry->address += input_section->output_offset;
1814 return bfd_reloc_ok;
1815 }
1816
1817 if (output_bfd != NULL)
1818 return bfd_reloc_continue;
1819
1820 relocation = symbol->value + symbol->section->output_section->vma
1821 + symbol->section->output_offset + reloc_entry->addend;
1822
1823 bfd_size_type octets = reloc_entry->address
1824 * bfd_octets_per_byte (abfd, input_section);
1825 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1826 input_section, octets))
1827 return bfd_reloc_outofrange;
1828
1829 unsigned int len = 0;
1830 bfd_byte *p = data + reloc_entry->address;
1831 bfd_vma old_value = _bfd_read_unsigned_leb128 (abfd, p, &len);
1832
1833 switch (howto->type)
1834 {
1835 case R_LARCH_ADD_ULEB128:
1836 relocation = old_value + relocation;
1837 break;
1838
1839 case R_LARCH_SUB_ULEB128:
1840 relocation = old_value - relocation;
1841 break;
1842 }
1843
1844 bfd_vma mask = (1 << (7 * len)) - 1;
1845 relocation = relocation & mask;
1846 loongarch_write_unsigned_leb128 (p, len, relocation);
1847 return bfd_reloc_ok;
1848 }
1849
1850 /* Write VALUE in uleb128 format to P.
1851 LEN is the uleb128 value length.
1852 Return a pointer to the byte following the last byte that was written. */
1853 bfd_byte *
1854 loongarch_write_unsigned_leb128 (bfd_byte *p, unsigned int len, bfd_vma value)
1855 {
1856 bfd_byte c;
1857 do
1858 {
1859 c = value & 0x7f;
1860 if (len > 1)
1861 c |= 0x80;
1862 *(p++) = c;
1863 value >>= 7;
1864 len--;
1865 }
1866 while (len);
1867 return p;
1868 }
1869
1870 int loongarch_get_uleb128_length (bfd_byte *buf)
1871 {
1872 unsigned int len = 0;
1873 _bfd_read_unsigned_leb128 (NULL, buf, &len);
1874 return len;
1875 }