1 /* LoongArch-specific support for ELF.
2 Copyright (C) 2021-2024 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_HOWTO (R_LARCH_TLS_DESC32, /* type (13). */
297 0, /* rightshift. */
298 4, /* size. */
299 32, /* bitsize. */
300 false, /* pc_relative. */
301 0, /* bitpos. */
302 complain_overflow_dont, /* complain_on_overflow. */
303 bfd_elf_generic_reloc, /* special_function. */
304 "R_LARCH_TLS_DESC32", /* name. */
305 false, /* partial_inplace. */
306 0, /* src_mask. */
307 ALL_ONES, /* dst_mask. */
308 false, /* pcrel_offset. */
309 BFD_RELOC_LARCH_TLS_DESC32, /* bfd_reloc_code_real_type. */
310 NULL, /* adjust_reloc_bits. */
311 NULL), /* larch_reloc_type_name. */
312
313 LOONGARCH_HOWTO (R_LARCH_TLS_DESC64, /* type (14). */
314 0, /* rightshift. */
315 4, /* size. */
316 64, /* bitsize. */
317 false, /* pc_relative. */
318 0, /* bitpos. */
319 complain_overflow_dont, /* complain_on_overflow. */
320 bfd_elf_generic_reloc, /* special_function. */
321 "R_LARCH_TLS_DESC64", /* name. */
322 false, /* partial_inplace. */
323 0, /* src_mask. */
324 ALL_ONES, /* dst_mask. */
325 false, /* pcrel_offset. */
326 BFD_RELOC_LARCH_TLS_DESC64, /* bfd_reloc_code_real_type. */
327 NULL, /* adjust_reloc_bits. */
328 NULL), /* larch_reloc_type_name. */
329
330 LOONGARCH_EMPTY_HOWTO (15),
331 LOONGARCH_EMPTY_HOWTO (16),
332 LOONGARCH_EMPTY_HOWTO (17),
333 LOONGARCH_EMPTY_HOWTO (18),
334 LOONGARCH_EMPTY_HOWTO (19),
335
336 LOONGARCH_HOWTO (R_LARCH_MARK_LA, /* type (20). */
337 0, /* rightshift. */
338 0, /* size. */
339 0, /* bitsize. */
340 false, /* pc_relative. */
341 0, /* bitpos. */
342 complain_overflow_signed, /* complain_on_overflow. */
343 bfd_elf_generic_reloc, /* special_function. */
344 "R_LARCH_MARK_LA", /* name. */
345 false, /* partial_inplace. */
346 0, /* src_mask. */
347 0, /* dst_mask. */
348 false, /* pcrel_offset */
349 BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */
350 NULL, /* adjust_reloc_bits */
351 NULL), /* larch_reloc_type_name */
352
353 LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
354 0, /* rightshift. */
355 0, /* size. */
356 0, /* bitsize. */
357 false, /* pc_relative. */
358 0, /* bitpos. */
359 complain_overflow_signed, /* complain_on_overflow. */
360 bfd_elf_generic_reloc, /* special_function. */
361 "R_LARCH_MARK_PCREL", /* name. */
362 false, /* partial_inplace. */
363 0, /* src_mask. */
364 0, /* dst_mask. */
365 false, /* pcrel_offset */
366 BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */
367 NULL, /* adjust_reloc_bits */
368 NULL), /* larch_reloc_type_name */
369
370 LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
371 2, /* rightshift. */
372 4, /* size. */
373 32, /* bitsize. */
374 true /* FIXME: somewhat use this. */, /* pc_relative. */
375 0, /* bitpos. */
376 complain_overflow_signed, /* complain_on_overflow. */
377 bfd_elf_generic_reloc, /* special_function. */
378 "R_LARCH_SOP_PUSH_PCREL", /* name. */
379 false, /* partial_inplace. */
380 0x03ffffff, /* src_mask. */
381 0x03ffffff, /* dst_mask. */
382 false, /* pcrel_offset */
383 BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */
384 NULL, /* adjust_reloc_bits */
385 NULL), /* larch_reloc_type_name */
386
387 /* type 23-37. */
388 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
389 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP),
390 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL),
391 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL),
392 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT),
393 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD),
394 LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL),
395 LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT),
396 LOONGARCH_DEFAULT_HOWTO (SOP_NOT),
397 LOONGARCH_DEFAULT_HOWTO (SOP_SUB),
398 LOONGARCH_DEFAULT_HOWTO (SOP_SL),
399 LOONGARCH_DEFAULT_HOWTO (SOP_SR),
400 LOONGARCH_DEFAULT_HOWTO (SOP_ADD),
401 LOONGARCH_DEFAULT_HOWTO (SOP_AND),
402 LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
403
404 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5, /* type (38). */
405 0, /* rightshift. */
406 4, /* size. */
407 5, /* bitsize. */
408 false, /* pc_relative. */
409 10, /* bitpos. */
410 complain_overflow_signed, /* complain_on_overflow. */
411 bfd_elf_generic_reloc, /* special_function. */
412 "R_LARCH_SOP_POP_32_S_10_5", /* name. */
413 false, /* partial_inplace. */
414 0, /* src_mask */
415 0x7c00, /* dst_mask */
416 false, /* pcrel_offset */
417 BFD_RELOC_LARCH_SOP_POP_32_S_10_5, /* bfd_reloc_code_real_type */
418 reloc_bits, /* adjust_reloc_bits */
419 NULL), /* larch_reloc_type_name */
420
421 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12, /* type (39). */
422 0, /* rightshift. */
423 4, /* size. */
424 12, /* bitsize. */
425 false, /* pc_relative. */
426 10, /* bitpos. */
427 complain_overflow_unsigned, /* complain_on_overflow. */
428 bfd_elf_generic_reloc, /* special_function. */
429 "R_LARCH_SOP_POP_32_U_10_12", /* name. */
430 false, /* partial_inplace. */
431 0, /* src_mask */
432 0x3ffc00, /* dst_mask */
433 false, /* pcrel_offset */
434 BFD_RELOC_LARCH_SOP_POP_32_U_10_12, /* bfd_reloc_code_real_type */
435 reloc_bits, /* adjust_reloc_bits */
436 NULL), /* larch_reloc_type_name */
437
438 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12, /* type (40). */
439 0, /* rightshift. */
440 4, /* size. */
441 12, /* bitsize. */
442 false, /* pc_relative. */
443 10, /* bitpos. */
444 complain_overflow_signed, /* complain_on_overflow. */
445 bfd_elf_generic_reloc, /* special_function. */
446 "R_LARCH_SOP_POP_32_S_10_12", /* name. */
447 false, /* partial_inplace. */
448 0, /* src_mask */
449 0x3ffc00, /* dst_mask */
450 false, /* pcrel_offset */
451 BFD_RELOC_LARCH_SOP_POP_32_S_10_12, /* bfd_reloc_code_real_type */
452 reloc_bits, /* adjust_reloc_bits */
453 NULL), /* larch_reloc_type_name */
454
455 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16, /* type (41). */
456 0, /* rightshift. */
457 4, /* size. */
458 16, /* bitsize. */
459 false, /* pc_relative. */
460 10, /* bitpos. */
461 complain_overflow_signed, /* complain_on_overflow. */
462 bfd_elf_generic_reloc, /* special_function. */
463 "R_LARCH_SOP_POP_32_S_10_16", /* name. */
464 false, /* partial_inplace. */
465 0, /* src_mask */
466 0x3fffc00, /* dst_mask */
467 false, /* pcrel_offset */
468 BFD_RELOC_LARCH_SOP_POP_32_S_10_16, /* bfd_reloc_code_real_type */
469 reloc_bits, /* adjust_reloc_bits */
470 NULL), /* larch_reloc_type_name */
471
472 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42). */
473 2, /* rightshift. */
474 4, /* size. */
475 16, /* bitsize. */
476 false, /* pc_relative. */
477 10, /* bitpos. */
478 complain_overflow_signed, /* complain_on_overflow. */
479 bfd_elf_generic_reloc, /* special_function. */
480 "R_LARCH_SOP_POP_32_S_10_16_S2", /* name. */
481 false, /* partial_inplace. */
482 0, /* src_mask */
483 0x3fffc00, /* dst_mask */
484 false, /* pcrel_offset */
485 BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2, /* bfd_reloc_code_real_type */
486 reloc_sign_bits, /* adjust_reloc_bits */
487 NULL), /* larch_reloc_type_name */
488
489 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20, /* type (43). */
490 0, /* rightshift. */
491 4, /* size. */
492 20, /* bitsize. */
493 false, /* pc_relative. */
494 5, /* bitpos. */
495 complain_overflow_signed, /* complain_on_overflow. */
496 bfd_elf_generic_reloc, /* special_function. */
497 "R_LARCH_SOP_POP_32_S_5_20", /* name. */
498 false, /* partial_inplace. */
499 0, /* src_mask */
500 0x1ffffe0, /* dst_mask */
501 false, /* pcrel_offset */
502 BFD_RELOC_LARCH_SOP_POP_32_S_5_20, /* bfd_reloc_code_real_type */
503 reloc_bits, /* adjust_reloc_bits */
504 NULL), /* larch_reloc_type_name */
505
506 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
507 /* type (44). */
508 2, /* rightshift. */
509 4, /* size. */
510 21, /* bitsize. */
511 false, /* pc_relative. */
512 0, /* bitpos. */
513 complain_overflow_signed, /* complain_on_overflow. */
514 bfd_elf_generic_reloc, /* special_function. */
515 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", /* name. */
516 false, /* partial_inplace. */
517 0xfc0003e0, /* src_mask */
518 0xfc0003e0, /* dst_mask */
519 false, /* pcrel_offset */
520 BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
521 /* bfd_reloc_code_real_type */
522 reloc_sign_bits, /* adjust_reloc_bits */
523 NULL), /* larch_reloc_type_name */
524
525 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
526 2, /* rightshift. */
527 4, /* size. */
528 26, /* bitsize. */
529 false, /* pc_relative. */
530 0, /* bitpos. */
531 complain_overflow_signed, /* complain_on_overflow. */
532 bfd_elf_generic_reloc, /* special_function. */
533 "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", /* name. */
534 false, /* partial_inplace. */
535 0, /* src_mask */
536 0x03ffffff, /* dst_mask */
537 false, /* pcrel_offset */
538 BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
539 /* bfd_reloc_code_real_type */
540 reloc_sign_bits, /* adjust_reloc_bits */
541 NULL), /* larch_reloc_type_name */
542
543 LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
544 0, /* rightshift. */
545 4, /* size. */
546 32, /* bitsize. */
547 false, /* pc_relative. */
548 0, /* bitpos. */
549 complain_overflow_unsigned, /* complain_on_overflow. */
550 bfd_elf_generic_reloc, /* special_function. */
551 "R_LARCH_SOP_POP_32_S_U", /* name. */
552 false, /* partial_inplace. */
553 0xffffffff00000000, /* src_mask */
554 0x00000000ffffffff, /* dst_mask */
555 false, /* pcrel_offset */
556 BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */
557 reloc_bits, /* adjust_reloc_bits */
558 NULL), /* larch_reloc_type_name */
559
560 /* 8-bit in-place addition, for local label subtraction. */
561 LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
562 0, /* rightshift. */
563 1, /* size. */
564 8, /* bitsize. */
565 false, /* pc_relative. */
566 0, /* bitpos. */
567 complain_overflow_dont, /* complain_on_overflow. */
568 loongarch_elf_add_sub_reloc, /* special_function. */
569 "R_LARCH_ADD8", /* name. */
570 false, /* partial_inplace. */
571 0, /* src_mask. */
572 0xff, /* dst_mask. */
573 false, /* pcrel_offset. */
574 BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type. */
575 NULL, /* adjust_reloc_bits. */
576 NULL), /* larch_reloc_type_name. */
577
578 /* 16-bit in-place addition, for local label subtraction. */
579 LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
580 0, /* rightshift. */
581 2, /* size. */
582 16, /* bitsize. */
583 false, /* pc_relative. */
584 0, /* bitpos. */
585 complain_overflow_dont, /* complain_on_overflow. */
586 loongarch_elf_add_sub_reloc, /* special_function. */
587 "R_LARCH_ADD16", /* name. */
588 false, /* partial_inplace. */
589 0, /* src_mask. */
590 0xffff, /* dst_mask. */
591 false, /* pcrel_offset. */
592 BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type. */
593 NULL, /* adjust_reloc_bits. */
594 NULL), /* larch_reloc_type_name. */
595
596 /* 24-bit in-place addition, for local label subtraction. */
597 LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
598 0, /* rightshift. */
599 3, /* size. */
600 24, /* bitsize. */
601 false, /* pc_relative. */
602 0, /* bitpos. */
603 complain_overflow_dont, /* complain_on_overflow. */
604 loongarch_elf_add_sub_reloc, /* special_function. */
605 "R_LARCH_ADD24", /* name. */
606 false, /* partial_inplace. */
607 0, /* src_mask. */
608 0xffffff, /* dst_mask. */
609 false, /* pcrel_offset. */
610 BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type. */
611 NULL, /* adjust_reloc_bits. */
612 NULL), /* larch_reloc_type_name. */
613
614 /* 32-bit in-place addition, for local label subtraction. */
615 LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
616 0, /* rightshift. */
617 4, /* size. */
618 32, /* bitsize. */
619 false, /* pc_relative. */
620 0, /* bitpos. */
621 complain_overflow_dont, /* complain_on_overflow. */
622 loongarch_elf_add_sub_reloc, /* special_function. */
623 "R_LARCH_ADD32", /* name. */
624 false, /* partial_inplace. */
625 0, /* src_mask. */
626 0xffffffff, /* dst_mask. */
627 false, /* pcrel_offset. */
628 BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type. */
629 NULL, /* adjust_reloc_bits. */
630 NULL), /* larch_reloc_type_name. */
631
632 /* 64-bit in-place addition, for local label subtraction. */
633 LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
634 0, /* rightshift. */
635 8, /* size. */
636 64, /* bitsize. */
637 false, /* pc_relative. */
638 0, /* bitpos. */
639 complain_overflow_dont, /* complain_on_overflow. */
640 loongarch_elf_add_sub_reloc, /* special_function. */
641 "R_LARCH_ADD64", /* name. */
642 false, /* partial_inplace. */
643 0, /* src_mask. */
644 ALL_ONES, /* dst_mask. */
645 false, /* pcrel_offset. */
646 BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type. */
647 NULL, /* adjust_reloc_bits. */
648 NULL), /* larch_reloc_type_name. */
649
650 /* 8-bit in-place subtraction, for local label subtraction. */
651 LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
652 0, /* rightshift. */
653 1, /* size. */
654 8, /* bitsize. */
655 false, /* pc_relative. */
656 0, /* bitpos. */
657 complain_overflow_dont, /* complain_on_overflow. */
658 loongarch_elf_add_sub_reloc, /* special_function. */
659 "R_LARCH_SUB8", /* name. */
660 false, /* partial_inplace. */
661 0, /* src_mask. */
662 0xff, /* dst_mask. */
663 false, /* pcrel_offset. */
664 BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type. */
665 NULL, /* adjust_reloc_bits. */
666 NULL), /* larch_reloc_type_name. */
667
668 /* 16-bit in-place subtraction, for local label subtraction. */
669 LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
670 0, /* rightshift. */
671 2, /* size. */
672 16, /* bitsize. */
673 false, /* pc_relative. */
674 0, /* bitpos. */
675 complain_overflow_dont, /* complain_on_overflow. */
676 loongarch_elf_add_sub_reloc, /* special_function. */
677 "R_LARCH_SUB16", /* name. */
678 false, /* partial_inplace. */
679 0, /* src_mask. */
680 0xffff, /* dst_mask. */
681 false, /* pcrel_offset. */
682 BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type. */
683 NULL, /* adjust_reloc_bits. */
684 NULL), /* larch_reloc_type_name. */
685
686 /* 24-bit in-place subtraction, for local label subtraction. */
687 LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
688 0, /* rightshift. */
689 3, /* size. */
690 24, /* bitsize. */
691 false, /* pc_relative. */
692 0, /* bitpos. */
693 complain_overflow_dont, /* complain_on_overflow. */
694 loongarch_elf_add_sub_reloc, /* special_function. */
695 "R_LARCH_SUB24", /* name. */
696 false, /* partial_inplace. */
697 0, /* src_mask. */
698 0xffffff, /* dst_mask. */
699 false, /* pcrel_offset. */
700 BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type. */
701 NULL, /* adjust_reloc_bits. */
702 NULL), /* larch_reloc_type_name. */
703
704 /* 32-bit in-place subtraction, for local label subtraction. */
705 LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
706 0, /* rightshift. */
707 4, /* size. */
708 32, /* bitsize. */
709 false, /* pc_relative. */
710 0, /* bitpos. */
711 complain_overflow_dont, /* complain_on_overflow. */
712 loongarch_elf_add_sub_reloc, /* special_function. */
713 "R_LARCH_SUB32", /* name. */
714 false, /* partial_inplace. */
715 0, /* src_mask. */
716 0xffffffff, /* dst_mask. */
717 false, /* pcrel_offset. */
718 BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type. */
719 NULL, /* adjust_reloc_bits. */
720 NULL), /* larch_reloc_type_name. */
721
722 /* 64-bit in-place subtraction, for local label subtraction. */
723 LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
724 0, /* rightshift. */
725 8, /* size. */
726 64, /* bitsize. */
727 false, /* pc_relative. */
728 0, /* bitpos. */
729 complain_overflow_dont, /* complain_on_overflow. */
730 loongarch_elf_add_sub_reloc, /* special_function. */
731 "R_LARCH_SUB64", /* name. */
732 false, /* partial_inplace. */
733 0, /* src_mask. */
734 ALL_ONES, /* dst_mask. */
735 false, /* pcrel_offset. */
736 BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type. */
737 NULL, /* adjust_reloc_bits. */
738 NULL), /* larch_reloc_type_name. */
739
740 LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
741 0, /* rightshift. */
742 0, /* size. */
743 0, /* bitsize. */
744 false, /* pc_relative. */
745 0, /* bitpos. */
746 complain_overflow_signed, /* complain_on_overflow. */
747 bfd_elf_generic_reloc, /* special_function. */
748 "R_LARCH_GNU_VTINHERIT", /* name. */
749 false, /* partial_inplace. */
750 0, /* src_mask */
751 0, /* dst_mask */
752 false, /* pcrel_offset */
753 BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
754 NULL, /* adjust_reloc_bits */
755 NULL), /* larch_reloc_type_name */
756
757 LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
758 0, /* rightshift. */
759 0, /* size. */
760 0, /* bitsize. */
761 false, /* pc_relative. */
762 0, /* bitpos. */
763 complain_overflow_signed, /* complain_on_overflow. */
764 NULL, /* special_function. */
765 "R_LARCH_GNU_VTENTRY", /* name. */
766 false, /* partial_inplace. */
767 0, /* src_mask */
768 0, /* dst_mask */
769 false, /* pcrel_offset */
770 BFD_RELOC_NONE, /* bfd_reloc_code_real_type */
771 NULL, /* adjust_reloc_bits */
772 NULL), /* larch_reloc_type_name */
773
774 LOONGARCH_EMPTY_HOWTO (59),
775 LOONGARCH_EMPTY_HOWTO (60),
776 LOONGARCH_EMPTY_HOWTO (61),
777 LOONGARCH_EMPTY_HOWTO (62),
778 LOONGARCH_EMPTY_HOWTO (63),
779
780 /* New reloc types. */
781 LOONGARCH_HOWTO (R_LARCH_B16, /* type (64). */
782 2, /* rightshift. */
783 4, /* size. */
784 16, /* bitsize. */
785 false, /* pc_relative. */
786 10, /* bitpos. */
787 complain_overflow_signed, /* complain_on_overflow. */
788 bfd_elf_generic_reloc, /* special_function. */
789 "R_LARCH_B16", /* name. */
790 false, /* partial_inplace. */
791 0, /* src_mask. */
792 0x3fffc00, /* dst_mask. */
793 false, /* pcrel_offset. */
794 BFD_RELOC_LARCH_B16, /* bfd_reloc_code_real_type. */
795 reloc_sign_bits, /* adjust_reloc_bits. */
796 "b16"), /* larch_reloc_type_name. */
797
798 LOONGARCH_HOWTO (R_LARCH_B21, /* type (65). */
799 2, /* rightshift. */
800 4, /* size. */
801 21, /* bitsize. */
802 false, /* pc_relative. */
803 0, /* bitpos. */
804 complain_overflow_signed, /* complain_on_overflow. */
805 bfd_elf_generic_reloc, /* special_function. */
806 "R_LARCH_B21", /* name. */
807 false, /* partial_inplace. */
808 0, /* src_mask. */
809 0x3fffc1f, /* dst_mask. */
810 false, /* pcrel_offset. */
811 BFD_RELOC_LARCH_B21, /* bfd_reloc_code_real_type. */
812 reloc_sign_bits, /* adjust_reloc_bits. */
813 "b21"), /* larch_reloc_type_name. */
814
815 LOONGARCH_HOWTO (R_LARCH_B26, /* type (66). */
816 2, /* rightshift. */
817 4, /* size. */
818 26, /* bitsize. */
819 false, /* pc_relative. */
820 0, /* bitpos. */
821 complain_overflow_signed, /* complain_on_overflow. */
822 bfd_elf_generic_reloc, /* special_function. */
823 "R_LARCH_B26", /* name. */
824 false, /* partial_inplace. */
825 0, /* src_mask. */
826 0x03ffffff, /* dst_mask. */
827 false, /* pcrel_offset. */
828 BFD_RELOC_LARCH_B26, /* bfd_reloc_code_real_type. */
829 reloc_sign_bits, /* adjust_reloc_bits. */
830 "b26"), /* larch_reloc_type_name. */
831
832 LOONGARCH_HOWTO (R_LARCH_ABS_HI20, /* type (67). */
833 12, /* rightshift. */
834 4, /* size. */
835 20, /* bitsize. */
836 false, /* pc_relative. */
837 5, /* bitpos. */
838 complain_overflow_signed, /* complain_on_overflow. */
839 bfd_elf_generic_reloc, /* special_function. */
840 "R_LARCH_ABS_HI20", /* name. */
841 false, /* partial_inplace. */
842 0, /* src_mask */
843 0x1ffffe0, /* dst_mask */
844 false, /* pcrel_offset */
845 BFD_RELOC_LARCH_ABS_HI20, /* bfd_reloc_code_real_type */
846 reloc_bits, /* adjust_reloc_bits */
847 "abs_hi20"), /* larch_reloc_type_name */
848
849 LOONGARCH_HOWTO (R_LARCH_ABS_LO12, /* type (68). */
850 0, /* rightshift. */
851 4, /* size. */
852 12, /* bitsize. */
853 false, /* pc_relative. */
854 10, /* bitpos. */
855 complain_overflow_unsigned, /* complain_on_overflow. */
856 bfd_elf_generic_reloc, /* special_function. */
857 "R_LARCH_ABS_LO12", /* name. */
858 false, /* partial_inplace. */
859 0, /* src_mask */
860 0x3ffc00, /* dst_mask */
861 false, /* pcrel_offset */
862 BFD_RELOC_LARCH_ABS_LO12, /* bfd_reloc_code_real_type */
863 reloc_bits, /* adjust_reloc_bits */
864 "abs_lo12"), /* larch_reloc_type_name */
865
866 LOONGARCH_HOWTO (R_LARCH_ABS64_LO20, /* type (69). */
867 32, /* rightshift. */
868 4, /* size. */
869 20, /* bitsize. */
870 false, /* pc_relative. */
871 5, /* bitpos. */
872 complain_overflow_signed, /* complain_on_overflow. */
873 bfd_elf_generic_reloc, /* special_function. */
874 "R_LARCH_ABS64_LO20", /* name. */
875 false, /* partial_inplace. */
876 0, /* src_mask */
877 0x1ffffe0, /* dst_mask */
878 false, /* pcrel_offset */
879 BFD_RELOC_LARCH_ABS64_LO20, /* bfd_reloc_code_real_type */
880 reloc_bits, /* adjust_reloc_bits */
881 "abs64_lo20"), /* larch_reloc_type_name */
882
883 LOONGARCH_HOWTO (R_LARCH_ABS64_HI12, /* type (70). */
884 52, /* rightshift. */
885 4, /* size. */
886 12, /* bitsize. */
887 false, /* pc_relative. */
888 10, /* bitpos. */
889 complain_overflow_signed, /* complain_on_overflow. */
890 bfd_elf_generic_reloc, /* special_function. */
891 "R_LARCH_ABS64_HI12", /* name. */
892 false, /* partial_inplace. */
893 0, /* src_mask */
894 0x3ffc00, /* dst_mask */
895 false, /* pcrel_offset */
896 BFD_RELOC_LARCH_ABS64_HI12, /* bfd_reloc_code_real_type */
897 reloc_bits, /* adjust_reloc_bits */
898 "abs64_hi12"), /* larch_reloc_type_name */
899
900 LOONGARCH_HOWTO (R_LARCH_PCALA_HI20, /* type (71). */
901 12, /* rightshift. */
902 4, /* size. */
903 20, /* bitsize. */
904 false, /* pc_relative. */
905 5, /* bitpos. */
906 complain_overflow_signed, /* complain_on_overflow. */
907 bfd_elf_generic_reloc, /* special_function. */
908 "R_LARCH_PCALA_HI20", /* name. */
909 false, /* partial_inplace. */
910 0, /* src_mask */
911 0x1ffffe0, /* dst_mask */
912 false, /* pcrel_offset */
913 BFD_RELOC_LARCH_PCALA_HI20, /* bfd_reloc_code_real_type */
914 reloc_bits, /* adjust_reloc_bits */
915 "pc_hi20"), /* larch_reloc_type_name */
916
917 LOONGARCH_HOWTO (R_LARCH_PCALA_LO12, /* type (72). */
918 0, /* rightshift. */
919 4, /* size. */
920 12, /* bitsize. */
921 false, /* pc_relative. */
922 10, /* bitpos. */
923 complain_overflow_signed, /* complain_on_overflow. */
924 bfd_elf_generic_reloc, /* special_function. */
925 "R_LARCH_PCALA_LO12", /* name. */
926 false, /* partial_inplace. */
927 0, /* src_mask */
928 0x3ffc00, /* dst_mask */
929 false, /* pcrel_offset */
930 BFD_RELOC_LARCH_PCALA_LO12, /* bfd_reloc_code_real_type */
931 reloc_bits, /* adjust_reloc_bits */
932 "pc_lo12"), /* larch_reloc_type_name */
933
934 LOONGARCH_HOWTO (R_LARCH_PCALA64_LO20, /* type (73). */
935 32, /* rightshift. */
936 4, /* size. */
937 20, /* bitsize. */
938 false, /* pc_relative. */
939 5, /* bitpos. */
940 complain_overflow_signed, /* complain_on_overflow. */
941 bfd_elf_generic_reloc, /* special_function. */
942 "R_LARCH_PCALA64_LO20", /* name. */
943 false, /* partial_inplace. */
944 0, /* src_mask */
945 0x1ffffe0, /* dst_mask */
946 false, /* pcrel_offset */
947 BFD_RELOC_LARCH_PCALA64_LO20, /* bfd_reloc_code_real_type */
948 reloc_bits, /* adjust_reloc_bits */
949 "pc64_lo20"), /* larch_reloc_type_name */
950
951 LOONGARCH_HOWTO (R_LARCH_PCALA64_HI12, /* type (74). */
952 52, /* rightshift. */
953 4, /* size. */
954 12, /* bitsize. */
955 false, /* pc_relative. */
956 10, /* bitpos. */
957 complain_overflow_signed, /* complain_on_overflow. */
958 bfd_elf_generic_reloc, /* special_function. */
959 "R_LARCH_PCALA64_HI12", /* name. */
960 false, /* partial_inplace. */
961 0, /* src_mask */
962 0x3ffc00, /* dst_mask */
963 false, /* pcrel_offset */
964 BFD_RELOC_LARCH_PCALA64_HI12, /* bfd_reloc_code_real_type */
965 reloc_bits, /* adjust_reloc_bits */
966 "pc64_hi12"), /* larch_reloc_type_name */
967
968 LOONGARCH_HOWTO (R_LARCH_GOT_PC_HI20, /* type (75). */
969 12, /* rightshift. */
970 4, /* size. */
971 20, /* bitsize. */
972 false, /* pc_relative. */
973 5, /* bitpos. */
974 complain_overflow_signed, /* complain_on_overflow. */
975 bfd_elf_generic_reloc, /* special_function. */
976 "R_LARCH_GOT_PC_HI20", /* name. */
977 false, /* partial_inplace. */
978 0, /* src_mask */
979 0x1ffffe0, /* dst_mask */
980 false, /* pcrel_offset */
981 BFD_RELOC_LARCH_GOT_PC_HI20, /* bfd_reloc_code_real_type */
982 reloc_bits, /* adjust_reloc_bits */
983 "got_pc_hi20"), /* larch_reloc_type_name */
984
985 LOONGARCH_HOWTO (R_LARCH_GOT_PC_LO12, /* type (76). */
986 0, /* rightshift. */
987 4, /* size. */
988 12, /* bitsize. */
989 false, /* pc_relative. */
990 10, /* bitpos. */
991 complain_overflow_signed, /* complain_on_overflow. */
992 bfd_elf_generic_reloc, /* special_function. */
993 "R_LARCH_GOT_PC_LO12", /* name. */
994 false, /* partial_inplace. */
995 0, /* src_mask */
996 0x3ffc00, /* dst_mask */
997 false, /* pcrel_offset */
998 BFD_RELOC_LARCH_GOT_PC_LO12, /* bfd_reloc_code_real_type */
999 reloc_bits, /* adjust_reloc_bits */
1000 "got_pc_lo12"), /* larch_reloc_type_name */
1001
1002 LOONGARCH_HOWTO (R_LARCH_GOT64_PC_LO20, /* type (77). */
1003 32, /* rightshift. */
1004 4, /* size. */
1005 20, /* bitsize. */
1006 false, /* pc_relative. */
1007 5, /* bitpos. */
1008 complain_overflow_signed, /* complain_on_overflow. */
1009 bfd_elf_generic_reloc, /* special_function. */
1010 "R_LARCH_GOT64_PC_LO20", /* name. */
1011 false, /* partial_inplace. */
1012 0, /* src_mask */
1013 0x1ffffe0, /* dst_mask */
1014 false, /* pcrel_offset */
1015 BFD_RELOC_LARCH_GOT64_PC_LO20, /* bfd_reloc_code_real_type */
1016 reloc_bits, /* adjust_reloc_bits */
1017 "got64_pc_lo20"), /* larch_reloc_type_name */
1018
1019 LOONGARCH_HOWTO (R_LARCH_GOT64_PC_HI12, /* type (78). */
1020 52, /* rightshift. */
1021 4, /* size. */
1022 12, /* bitsize. */
1023 false, /* pc_relative. */
1024 10, /* bitpos. */
1025 complain_overflow_signed, /* complain_on_overflow. */
1026 bfd_elf_generic_reloc, /* special_function. */
1027 "R_LARCH_GOT64_PC_HI12", /* name. */
1028 false, /* partial_inplace. */
1029 0, /* src_mask */
1030 0x3ffc00, /* dst_mask */
1031 false, /* pcrel_offset */
1032 BFD_RELOC_LARCH_GOT64_PC_HI12, /* bfd_reloc_code_real_type */
1033 reloc_bits, /* adjust_reloc_bits */
1034 "got64_pc_hi12"), /* larch_reloc_type_name */
1035
1036 LOONGARCH_HOWTO (R_LARCH_GOT_HI20, /* type (79). */
1037 12, /* rightshift. */
1038 4, /* size. */
1039 20, /* bitsize. */
1040 false, /* pc_relative. */
1041 5, /* bitpos. */
1042 complain_overflow_signed, /* complain_on_overflow. */
1043 bfd_elf_generic_reloc, /* special_function. */
1044 "R_LARCH_GOT_HI20", /* name. */
1045 false, /* partial_inplace. */
1046 0, /* src_mask */
1047 0x1ffffe0, /* dst_mask */
1048 false, /* pcrel_offset */
1049 BFD_RELOC_LARCH_GOT_HI20, /* bfd_reloc_code_real_type */
1050 reloc_bits, /* adjust_reloc_bits */
1051 "got_hi20"), /* larch_reloc_type_name */
1052
1053 LOONGARCH_HOWTO (R_LARCH_GOT_LO12, /* type (80). */
1054 0, /* rightshift. */
1055 4, /* size. */
1056 12, /* bitsize. */
1057 false, /* pc_relative. */
1058 10, /* bitpos. */
1059 complain_overflow_signed, /* complain_on_overflow. */
1060 bfd_elf_generic_reloc, /* special_function. */
1061 "R_LARCH_GOT_LO12", /* name. */
1062 false, /* partial_inplace. */
1063 0, /* src_mask */
1064 0x3ffc00, /* dst_mask */
1065 false, /* pcrel_offset */
1066 BFD_RELOC_LARCH_GOT_LO12, /* bfd_reloc_code_real_type */
1067 reloc_bits, /* adjust_reloc_bits */
1068 "got_lo12"), /* larch_reloc_type_name */
1069
1070 LOONGARCH_HOWTO (R_LARCH_GOT64_LO20, /* type (81). */
1071 32, /* rightshift. */
1072 4, /* size. */
1073 20, /* bitsize. */
1074 false, /* pc_relative. */
1075 5, /* bitpos. */
1076 complain_overflow_signed, /* complain_on_overflow. */
1077 bfd_elf_generic_reloc, /* special_function. */
1078 "R_LARCH_GOT64_LO20", /* name. */
1079 false, /* partial_inplace. */
1080 0, /* src_mask */
1081 0x1ffffe0, /* dst_mask */
1082 false, /* pcrel_offset */
1083 BFD_RELOC_LARCH_GOT64_LO20, /* bfd_reloc_code_real_type */
1084 reloc_bits, /* adjust_reloc_bits */
1085 "got64_lo20"), /* larch_reloc_type_name */
1086
1087 LOONGARCH_HOWTO (R_LARCH_GOT64_HI12, /* type (82). */
1088 52, /* rightshift. */
1089 4, /* size. */
1090 12, /* bitsize. */
1091 false, /* pc_relative. */
1092 10, /* bitpos. */
1093 complain_overflow_signed, /* complain_on_overflow. */
1094 bfd_elf_generic_reloc, /* special_function. */
1095 "R_LARCH_GOT64_HI12", /* name. */
1096 false, /* partial_inplace. */
1097 0, /* src_mask */
1098 0x3ffc00, /* dst_mask */
1099 false, /* pcrel_offset */
1100 BFD_RELOC_LARCH_GOT64_HI12, /* bfd_reloc_code_real_type */
1101 reloc_bits, /* adjust_reloc_bits */
1102 "got64_hi12"), /* larch_reloc_type_name */
1103
1104 LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20, /* type (83). */
1105 12, /* rightshift. */
1106 4, /* size. */
1107 20, /* bitsize. */
1108 false, /* pc_relative. */
1109 5, /* bitpos. */
1110 complain_overflow_signed, /* complain_on_overflow. */
1111 bfd_elf_generic_reloc, /* special_function. */
1112 "R_LARCH_TLS_LE_HI20", /* name. */
1113 false, /* partial_inplace. */
1114 0, /* src_mask */
1115 0x1ffffe0, /* dst_mask */
1116 false, /* pcrel_offset */
1117 BFD_RELOC_LARCH_TLS_LE_HI20, /* bfd_reloc_code_real_type */
1118 reloc_bits, /* adjust_reloc_bits */
1119 "le_hi20"), /* larch_reloc_type_name */
1120
1121 LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12, /* type (84). */
1122 0, /* rightshift. */
1123 4, /* size. */
1124 12, /* bitsize. */
1125 false, /* pc_relative. */
1126 10, /* bitpos. */
1127 complain_overflow_unsigned, /* complain_on_overflow. */
1128 bfd_elf_generic_reloc, /* special_function. */
1129 "R_LARCH_TLS_LE_LO12", /* name. */
1130 false, /* partial_inplace. */
1131 0, /* src_mask */
1132 0x3ffc00, /* dst_mask */
1133 false, /* pcrel_offset */
1134 BFD_RELOC_LARCH_TLS_LE_LO12, /* bfd_reloc_code_real_type */
1135 reloc_bits, /* adjust_reloc_bits */
1136 "le_lo12"), /* larch_reloc_type_name */
1137
1138 LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20, /* type (85). */
1139 32, /* rightshift. */
1140 4, /* size. */
1141 20, /* bitsize. */
1142 false, /* pc_relative. */
1143 5, /* bitpos. */
1144 complain_overflow_signed, /* complain_on_overflow. */
1145 bfd_elf_generic_reloc, /* special_function. */
1146 "R_LARCH_TLS_LE64_LO20", /* name. */
1147 false, /* partial_inplace. */
1148 0, /* src_mask */
1149 0x1ffffe0, /* dst_mask */
1150 false, /* pcrel_offset */
1151 BFD_RELOC_LARCH_TLS_LE64_LO20, /* bfd_reloc_code_real_type */
1152 reloc_bits, /* adjust_reloc_bits */
1153 "le64_lo20"), /* larch_reloc_type_name */
1154
1155 LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12, /* type (86). */
1156 52, /* rightshift. */
1157 4, /* size. */
1158 12, /* bitsize. */
1159 false, /* pc_relative. */
1160 10, /* bitpos. */
1161 complain_overflow_signed, /* complain_on_overflow. */
1162 bfd_elf_generic_reloc, /* special_function. */
1163 "R_LARCH_TLS_LE64_HI12", /* name. */
1164 false, /* partial_inplace. */
1165 0, /* src_mask */
1166 0x3ffc00, /* dst_mask */
1167 false, /* pcrel_offset */
1168 BFD_RELOC_LARCH_TLS_LE64_HI12, /* bfd_reloc_code_real_type */
1169 reloc_bits, /* adjust_reloc_bits */
1170 "le64_hi12"), /* larch_reloc_type_name */
1171
1172 LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20, /* type (87). */
1173 12, /* rightshift. */
1174 4, /* size. */
1175 20, /* bitsize. */
1176 false, /* pc_relative. */
1177 5, /* bitpos. */
1178 complain_overflow_signed, /* complain_on_overflow. */
1179 bfd_elf_generic_reloc, /* special_function. */
1180 "R_LARCH_TLS_IE_PC_HI20", /* name. */
1181 false, /* partial_inplace. */
1182 0, /* src_mask */
1183 0x1ffffe0, /* dst_mask */
1184 false, /* pcrel_offset */
1185 BFD_RELOC_LARCH_TLS_IE_PC_HI20, /* bfd_reloc_code_real_type */
1186 reloc_bits, /* adjust_reloc_bits */
1187 "ie_pc_hi20"), /* larch_reloc_type_name */
1188
1189 LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12, /* type (88). */
1190 0, /* rightshift. */
1191 4, /* size. */
1192 12, /* bitsize. */
1193 false, /* pc_relative. */
1194 10, /* bitpos. */
1195 complain_overflow_signed, /* complain_on_overflow. */
1196 bfd_elf_generic_reloc, /* special_function. */
1197 "R_LARCH_TLS_IE_PC_LO12", /* name. */
1198 false, /* partial_inplace. */
1199 0, /* src_mask */
1200 0x3ffc00, /* dst_mask */
1201 false, /* pcrel_offset */
1202 BFD_RELOC_LARCH_TLS_IE_PC_LO12, /* bfd_reloc_code_real_type */
1203 reloc_bits, /* adjust_reloc_bits */
1204 "ie_pc_lo12"), /* larch_reloc_type_name */
1205
1206 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20, /* type (89). */
1207 32, /* rightshift. */
1208 4, /* size. */
1209 20, /* bitsize. */
1210 false, /* pc_relative. */
1211 5, /* bitpos. */
1212 complain_overflow_signed, /* complain_on_overflow. */
1213 bfd_elf_generic_reloc, /* special_function. */
1214 "R_LARCH_TLS_IE64_PC_LO20", /* name. */
1215 false, /* partial_inplace. */
1216 0, /* src_mask */
1217 0x1ffffe0, /* dst_mask */
1218 false, /* pcrel_offset */
1219 BFD_RELOC_LARCH_TLS_IE64_PC_LO20, /* bfd_reloc_code_real_type */
1220 reloc_bits, /* adjust_reloc_bits */
1221 "ie64_pc_lo20"), /* larch_reloc_type_name */
1222
1223 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12, /* type (90). */
1224 52, /* rightshift. */
1225 4, /* size. */
1226 12, /* bitsize. */
1227 false, /* pc_relative. */
1228 10, /* bitpos. */
1229 complain_overflow_signed, /* complain_on_overflow. */
1230 bfd_elf_generic_reloc, /* special_function. */
1231 "R_LARCH_TLS_IE64_PC_HI12", /* name. */
1232 false, /* partial_inplace. */
1233 0, /* src_mask */
1234 0x3ffc00, /* dst_mask */
1235 false, /* pcrel_offset */
1236 BFD_RELOC_LARCH_TLS_IE64_PC_HI12, /* bfd_reloc_code_real_type */
1237 reloc_bits, /* adjust_reloc_bits */
1238 "ie64_pc_hi12"), /* larch_reloc_type_name */
1239
1240 LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20, /* type (91). */
1241 12, /* rightshift. */
1242 4, /* size. */
1243 20, /* bitsize. */
1244 false, /* pc_relative. */
1245 5, /* bitpos. */
1246 complain_overflow_signed, /* complain_on_overflow. */
1247 bfd_elf_generic_reloc, /* special_function. */
1248 "R_LARCH_TLS_IE_HI20", /* name. */
1249 false, /* partial_inplace. */
1250 0, /* src_mask */
1251 0x1ffffe0, /* dst_mask */
1252 false, /* pcrel_offset */
1253 BFD_RELOC_LARCH_TLS_IE_HI20, /* bfd_reloc_code_real_type */
1254 reloc_bits, /* adjust_reloc_bits */
1255 "ie_hi20"), /* larch_reloc_type_name */
1256
1257 LOONGARCH_HOWTO (R_LARCH_TLS_IE_LO12, /* type (92). */
1258 0, /* rightshift. */
1259 4, /* size. */
1260 12, /* bitsize. */
1261 false, /* pc_relative. */
1262 10, /* bitpos. */
1263 complain_overflow_signed, /* complain_on_overflow. */
1264 bfd_elf_generic_reloc, /* special_function. */
1265 "R_LARCH_TLS_IE_LO12", /* name. */
1266 false, /* partial_inplace. */
1267 0, /* src_mask */
1268 0x3ffc00, /* dst_mask */
1269 false, /* pcrel_offset */
1270 BFD_RELOC_LARCH_TLS_IE_LO12, /* bfd_reloc_code_real_type */
1271 reloc_bits, /* adjust_reloc_bits */
1272 "ie_lo12"), /* larch_reloc_type_name */
1273
1274 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20, /* type (93). */
1275 32, /* rightshift. */
1276 4, /* size. */
1277 20, /* bitsize. */
1278 false, /* pc_relative. */
1279 5, /* bitpos. */
1280 complain_overflow_signed, /* complain_on_overflow. */
1281 bfd_elf_generic_reloc, /* special_function. */
1282 "R_LARCH_TLS_IE64_LO20", /* name. */
1283 false, /* partial_inplace. */
1284 0, /* src_mask */
1285 0x1ffffe0, /* dst_mask */
1286 false, /* pcrel_offset */
1287 BFD_RELOC_LARCH_TLS_IE64_LO20, /* bfd_reloc_code_real_type */
1288 reloc_bits, /* adjust_reloc_bits */
1289 "ie64_lo20"), /* larch_reloc_type_name */
1290
1291 LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12, /* type (94). */
1292 52, /* rightshift. */
1293 4, /* size. */
1294 12, /* bitsize. */
1295 false, /* pc_relative. */
1296 10, /* bitpos. */
1297 complain_overflow_signed, /* complain_on_overflow. */
1298 bfd_elf_generic_reloc, /* special_function. */
1299 "R_LARCH_TLS_IE64_HI12", /* name. */
1300 false, /* partial_inplace. */
1301 0, /* src_mask */
1302 0x3ffc00, /* dst_mask */
1303 false, /* pcrel_offset */
1304 BFD_RELOC_LARCH_TLS_IE64_HI12, /* bfd_reloc_code_real_type */
1305 reloc_bits, /* adjust_reloc_bits */
1306 "ie64_hi12"), /* larch_reloc_type_name */
1307
1308 LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20, /* type (95). */
1309 12, /* rightshift. */
1310 4, /* size. */
1311 20, /* bitsize. */
1312 false, /* pc_relative. */
1313 5, /* bitpos. */
1314 complain_overflow_signed, /* complain_on_overflow. */
1315 bfd_elf_generic_reloc, /* special_function. */
1316 "R_LARCH_TLS_LD_PC_HI20", /* name. */
1317 false, /* partial_inplace. */
1318 0, /* src_mask */
1319 0x1ffffe0, /* dst_mask */
1320 false, /* pcrel_offset */
1321 BFD_RELOC_LARCH_TLS_LD_PC_HI20, /* bfd_reloc_code_real_type */
1322 reloc_bits, /* adjust_reloc_bits */
1323 "ld_pc_hi20"), /* larch_reloc_type_name */
1324
1325 LOONGARCH_HOWTO (R_LARCH_TLS_LD_HI20, /* type (96). */
1326 12, /* rightshift. */
1327 4, /* size. */
1328 20, /* bitsize. */
1329 false, /* pc_relative. */
1330 5, /* bitpos. */
1331 complain_overflow_signed, /* complain_on_overflow. */
1332 bfd_elf_generic_reloc, /* special_function. */
1333 "R_LARCH_TLS_LD_HI20", /* name. */
1334 false, /* partial_inplace. */
1335 0, /* src_mask */
1336 0x1ffffe0, /* dst_mask */
1337 false, /* pcrel_offset */
1338 BFD_RELOC_LARCH_TLS_LD_HI20, /* bfd_reloc_code_real_type */
1339 reloc_bits, /* adjust_reloc_bits */
1340 "ld_hi20"), /* larch_reloc_type_name */
1341
1342 LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20, /* type (97). */
1343 12, /* rightshift. */
1344 4, /* size. */
1345 20, /* bitsize. */
1346 false, /* pc_relative. */
1347 5, /* bitpos. */
1348 complain_overflow_signed, /* complain_on_overflow. */
1349 bfd_elf_generic_reloc, /* special_function. */
1350 "R_LARCH_TLS_GD_PC_HI20", /* name. */
1351 false, /* partial_inplace. */
1352 0, /* src_mask */
1353 0x1ffffe0, /* dst_mask */
1354 false, /* pcrel_offset */
1355 BFD_RELOC_LARCH_TLS_GD_PC_HI20, /* bfd_reloc_code_real_type */
1356 reloc_bits, /* adjust_reloc_bits */
1357 "gd_pc_hi20"), /* larch_reloc_type_name */
1358
1359 LOONGARCH_HOWTO (R_LARCH_TLS_GD_HI20, /* type (98). */
1360 12, /* rightshift. */
1361 4, /* size. */
1362 20, /* bitsize. */
1363 false, /* pc_relative. */
1364 5, /* bitpos. */
1365 complain_overflow_signed, /* complain_on_overflow. */
1366 bfd_elf_generic_reloc, /* special_function. */
1367 "R_LARCH_TLS_GD_HI20", /* name. */
1368 false, /* partial_inplace. */
1369 0, /* src_mask */
1370 0x1ffffe0, /* dst_mask */
1371 false, /* pcrel_offset */
1372 BFD_RELOC_LARCH_TLS_GD_HI20, /* bfd_reloc_code_real_type */
1373 reloc_bits, /* adjust_reloc_bits */
1374 "gd_hi20"), /* larch_reloc_type_name */
1375
1376 /* 32-bit PC relative. */
1377 LOONGARCH_HOWTO (R_LARCH_32_PCREL, /* type (99). */
1378 0, /* rightshift. */
1379 4, /* size. */
1380 32, /* bitsize. */
1381 true, /* pc_relative. */
1382 0, /* bitpos. */
1383 complain_overflow_signed, /* complain_on_overflow. */
1384 bfd_elf_generic_reloc, /* special_function. */
1385 "R_LARCH_32_PCREL", /* name. */
1386 false, /* partial_inplace. */
1387 0, /* src_mask */
1388 0xffffffff, /* dst_mask */
1389 false, /* pcrel_offset */
1390 BFD_RELOC_LARCH_32_PCREL, /* bfd_reloc_code_real_type */
1391 NULL, /* adjust_reloc_bits */
1392 NULL), /* larch_reloc_type_name */
1393
1394 /* The paired relocation may be relaxed. */
1395 LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (100). */
1396 0, /* rightshift */
1397 1, /* size */
1398 0, /* bitsize */
1399 false, /* pc_relative */
1400 0, /* bitpos */
1401 complain_overflow_dont, /* complain_on_overflow */
1402 bfd_elf_generic_reloc, /* special_function */
1403 "R_LARCH_RELAX", /* name */
1404 false, /* partial_inplace */
1405 0, /* src_mask */
1406 0, /* dst_mask */
1407 false, /* pcrel_offset */
1408 BFD_RELOC_LARCH_RELAX, /* bfd_reloc_code_real_type */
1409 NULL, /* adjust_reloc_bits */
1410 NULL), /* larch_reloc_type_name */
1411
1412 /* Delete relaxed instruction. */
1413 LOONGARCH_HOWTO (R_LARCH_DELETE, /* type (101). */
1414 0, /* rightshift. */
1415 0, /* size. */
1416 0, /* bitsize. */
1417 false, /* pc_relative. */
1418 0, /* bitpos. */
1419 complain_overflow_dont, /* complain_on_overflow. */
1420 bfd_elf_generic_reloc, /* special_function. */
1421 "R_LARCH_DELETE", /* name. */
1422 false, /* partial_inplace. */
1423 0, /* src_mask. */
1424 0, /* dst_mask. */
1425 false, /* pcrel_offset. */
1426 BFD_RELOC_LARCH_DELETE, /* bfd_reloc_code_real_type. */
1427 NULL, /* adjust_reloc_bits. */
1428 NULL), /* larch_reloc_type_name. */
1429
1430 /* Indicates an alignment statement. f the symbol index is 0,
1431 the addend indicates the number of bytes occupied by nop instructions
1432 at the relocation offset. The alignment boundary is specified by the
1433 addend rounded up to the next power of two.
1434 If the symbol index is not 0, the addend indicates the first and third
1435 expressions of .align. The lowest 8 bits are used to represent the first
1436 expression, other bits are used to represent the third expression. */
1437 LOONGARCH_HOWTO (R_LARCH_ALIGN, /* type (102). */
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_ALIGN", /* name. */
1446 false, /* partial_inplace. */
1447 0, /* src_mask. */
1448 0, /* dst_mask. */
1449 false, /* pcrel_offset. */
1450 BFD_RELOC_LARCH_ALIGN, /* bfd_reloc_code_real_type. */
1451 NULL, /* adjust_reloc_bits. */
1452 NULL), /* larch_reloc_type_name. */
1453
1454 /* For pcaddi and pcala_hi20 + pcala_lo12 can relax to pcrel_20. */
1455 LOONGARCH_HOWTO (R_LARCH_PCREL20_S2, /* type (103). */
1456 2, /* rightshift. */
1457 4, /* size. */
1458 20, /* bitsize. */
1459 false, /* pc_relative. */
1460 5, /* bitpos. */
1461 complain_overflow_signed, /* complain_on_overflow. */
1462 bfd_elf_generic_reloc, /* special_function. */
1463 "R_LARCH_PCREL20_S2", /* name. */
1464 false, /* partial_inplace. */
1465 0, /* src_mask. */
1466 0x1ffffe0, /* dst_mask. */
1467 false, /* pcrel_offset. */
1468 BFD_RELOC_LARCH_PCREL20_S2, /* bfd_reloc_code_real_type. */
1469 reloc_sign_bits, /* adjust_reloc_bits. */
1470 "pcrel_20"), /* larch_reloc_type_name. */
1471
1472 /* Canonical Frame Address. */
1473 LOONGARCH_HOWTO (R_LARCH_CFA, /* type (104). */
1474 0, /* rightshift. */
1475 0, /* size. */
1476 0, /* bitsize. */
1477 false, /* pc_relative. */
1478 0, /* bitpos. */
1479 complain_overflow_dont, /* complain_on_overflow. */
1480 bfd_elf_generic_reloc, /* special_function. */
1481 "R_LARCH_CFA", /* name. */
1482 false, /* partial_inplace. */
1483 0, /* src_mask. */
1484 0, /* dst_mask. */
1485 false, /* pcrel_offset. */
1486 BFD_RELOC_LARCH_CFA, /* bfd_reloc_code_real_type. */
1487 NULL, /* adjust_reloc_bits. */
1488 NULL), /* larch_reloc_type_name. */
1489
1490 /* 6-bit in-place addition, for local label subtraction
1491 to calculate DW_CFA_advance_loc. */
1492 LOONGARCH_HOWTO (R_LARCH_ADD6, /* type (105). */
1493 0, /* rightshift. */
1494 1, /* size. */
1495 8, /* bitsize. */
1496 false, /* pc_relative. */
1497 0, /* bitpos. */
1498 complain_overflow_dont, /* complain_on_overflow. */
1499 loongarch_elf_add_sub_reloc, /* special_function. */
1500 "R_LARCH_ADD6", /* name. */
1501 false, /* partial_inplace. */
1502 0, /* src_mask. */
1503 0x3f, /* dst_mask. */
1504 false, /* pcrel_offset. */
1505 BFD_RELOC_LARCH_ADD6, /* bfd_reloc_code_real_type. */
1506 reloc_bits, /* adjust_reloc_bits. */
1507 NULL), /* larch_reloc_type_name. */
1508
1509 /* 6-bit in-place subtraction, for local label subtraction
1510 to calculate DW_CFA_advance_loc. */
1511 LOONGARCH_HOWTO (R_LARCH_SUB6, /* type (106). */
1512 0, /* rightshift. */
1513 1, /* size. */
1514 8, /* bitsize. */
1515 false, /* pc_relative. */
1516 0, /* bitpos. */
1517 complain_overflow_dont, /* complain_on_overflow. */
1518 loongarch_elf_add_sub_reloc, /* special_function. */
1519 "R_LARCH_SUB6", /* name. */
1520 false, /* partial_inplace. */
1521 0, /* src_mask. */
1522 0x3f, /* dst_mask. */
1523 false, /* pcrel_offset. */
1524 BFD_RELOC_LARCH_SUB6, /* bfd_reloc_code_real_type. */
1525 reloc_bits, /* adjust_reloc_bits. */
1526 NULL), /* larch_reloc_type_name. */
1527
1528 /* The length of unsigned-leb128 is variable, just assume the
1529 size is one byte here.
1530 uleb128 in-place addition, for local label subtraction. */
1531 LOONGARCH_HOWTO (R_LARCH_ADD_ULEB128, /* type (107). */
1532 0, /* rightshift. */
1533 1, /* size. */
1534 0, /* bitsize. */
1535 false, /* pc_relative. */
1536 0, /* bitpos. */
1537 complain_overflow_dont, /* complain_on_overflow. */
1538 loongarch_elf_add_sub_reloc_uleb128, /* special_function. */
1539 "R_LARCH_ADD_ULEB128", /* name. */
1540 false, /* partial_inplace. */
1541 0, /* src_mask. */
1542 0, /* dst_mask. */
1543 false, /* pcrel_offset. */
1544 BFD_RELOC_LARCH_ADD_ULEB128, /* bfd_reloc_code_real_type. */
1545 NULL, /* adjust_reloc_bits. */
1546 NULL), /* larch_reloc_type_name. */
1547
1548 /* The length of unsigned-leb128 is variable, just assume the
1549 size is one byte here.
1550 uleb128 in-place subtraction, for local label subtraction. */
1551 LOONGARCH_HOWTO (R_LARCH_SUB_ULEB128, /* type (108). */
1552 0, /* rightshift. */
1553 1, /* size. */
1554 0, /* bitsize. */
1555 false, /* pc_relative. */
1556 0, /* bitpos. */
1557 complain_overflow_dont, /* complain_on_overflow. */
1558 loongarch_elf_add_sub_reloc_uleb128, /* special_function. */
1559 "R_LARCH_SUB_ULEB128", /* name. */
1560 false, /* partial_inplace. */
1561 0, /* src_mask. */
1562 0, /* dst_mask. */
1563 false, /* pcrel_offset. */
1564 BFD_RELOC_LARCH_SUB_ULEB128, /* bfd_reloc_code_real_type. */
1565 NULL, /* adjust_reloc_bits. */
1566 NULL), /* larch_reloc_type_name. */
1567
1568 /* 64-bit PC relative. */
1569 LOONGARCH_HOWTO (R_LARCH_64_PCREL, /* type (109). */
1570 0, /* rightshift. */
1571 8, /* size. */
1572 64, /* bitsize. */
1573 true, /* pc_relative. */
1574 0, /* bitpos. */
1575 complain_overflow_signed, /* complain_on_overflow. */
1576 bfd_elf_generic_reloc, /* special_function. */
1577 "R_LARCH_64_PCREL", /* name. */
1578 false, /* partial_inplace. */
1579 0, /* src_mask */
1580 0xffffffffffffffff, /* dst_mask */
1581 false, /* pcrel_offset */
1582 BFD_RELOC_LARCH_64_PCREL, /* bfd_reloc_code_real_type */
1583 NULL, /* adjust_reloc_bits */
1584 NULL), /* larch_reloc_type_name */
1585
1586 /* Used for medium code model function call pcaddu18i+jirl,
1587 these two instructions must adjacent. */
1588 LOONGARCH_HOWTO (R_LARCH_CALL36, /* type (110). */
1589 2, /* rightshift. */
1590 8, /* size. */
1591 36, /* bitsize. */
1592 true, /* pc_relative. */
1593 0, /* bitpos. */
1594 complain_overflow_signed, /* complain_on_overflow. */
1595 bfd_elf_generic_reloc, /* special_function. */
1596 "R_LARCH_CALL36", /* name. */
1597 false, /* partial_inplace. */
1598 0, /* src_mask. */
1599 0x03fffc0001ffffe0, /* dst_mask. */
1600 false, /* pcrel_offset. */
1601 BFD_RELOC_LARCH_CALL36, /* bfd_reloc_code_real_type. */
1602 reloc_sign_bits, /* adjust_reloc_bits. */
1603 "call36"), /* larch_reloc_type_name. */
1604
1605 /* TLS_DESC PCREL. */
1606 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PC_HI20, /* type (111). */
1607 12, /* rightshift. */
1608 4, /* size. */
1609 20, /* bitsize. */
1610 true, /* pc_relative. */
1611 5, /* bitpos. */
1612 complain_overflow_signed, /* complain_on_overflow. */
1613 bfd_elf_generic_reloc, /* special_function. */
1614 "R_LARCH_TLS_DESC_PC_HI20", /* name. */
1615 false, /* partial_inplace. */
1616 0, /* src_mask. */
1617 0x1ffffe0, /* dst_mask. */
1618 false, /* pcrel_offset. */
1619 BFD_RELOC_LARCH_TLS_DESC_PC_HI20, /* bfd_reloc_code_real_type. */
1620 reloc_bits, /* adjust_reloc_bits. */
1621 "desc_pc_hi20"), /* larch_reloc_type_name. */
1622
1623 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PC_LO12, /* type (112). */
1624 0, /* rightshift. */
1625 4, /* size. */
1626 12, /* bitsize. */
1627 true, /* pc_relative. */
1628 10, /* bitpos. */
1629 complain_overflow_signed, /* complain_on_overflow. */
1630 bfd_elf_generic_reloc, /* special_function. */
1631 "R_LARCH_TLS_DESC_PC_LO12", /* name. */
1632 false, /* partial_inplace. */
1633 0, /* src_mask. */
1634 0x3ffc00, /* dst_mask. */
1635 false, /* pcrel_offset. */
1636 BFD_RELOC_LARCH_TLS_DESC_PC_LO12, /* bfd_reloc_code_real_type. */
1637 reloc_bits, /* adjust_reloc_bits. */
1638 "desc_pc_lo12"), /* larch_reloc_type_name. */
1639
1640 /* TLS_DESC64 LARGE PCREL. */
1641 LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_PC_LO20, /* type (113). */
1642 32, /* rightshift. */
1643 8, /* size. */
1644 20, /* bitsize. */
1645 true, /* pc_relative. */
1646 5, /* bitpos. */
1647 complain_overflow_signed, /* complain_on_overflow. */
1648 bfd_elf_generic_reloc, /* special_function. */
1649 "R_LARCH_TLS_DESC64_PC_LO20", /* name. */
1650 false, /* partial_inplace. */
1651 0, /* src_mask. */
1652 0x1ffffe0, /* dst_mask. */
1653 false, /* pcrel_offset. */
1654 BFD_RELOC_LARCH_TLS_DESC64_PC_LO20, /* bfd_reloc_code_real_type. */
1655 reloc_bits, /* adjust_reloc_bits. */
1656 "desc64_pc_lo20"), /* larch_reloc_type_name. */
1657
1658 LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_PC_HI12, /* type (114). */
1659 52, /* rightshift. */
1660 8, /* size. */
1661 12, /* bitsize. */
1662 true, /* pc_relative. */
1663 10, /* bitpos. */
1664 complain_overflow_signed, /* complain_on_overflow. */
1665 bfd_elf_generic_reloc, /* special_function. */
1666 "R_LARCH_TLS_DESC64_PC_HI12", /* name. */
1667 false, /* partial_inplace. */
1668 0, /* src_mask. */
1669 0x3ffc00, /* dst_mask. */
1670 false, /* pcrel_offset. */
1671 BFD_RELOC_LARCH_TLS_DESC64_PC_HI12, /* bfd_reloc_code_real_type. */
1672 reloc_bits, /* adjust_reloc_bits. */
1673 "desc64_pc_hi12"), /* larch_reloc_type_name. */
1674
1675 /* TLS_DESC ABS. */
1676 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_HI20, /* type (115). */
1677 12, /* rightshift. */
1678 4, /* size. */
1679 20, /* bitsize. */
1680 false, /* pc_relative. */
1681 5, /* bitpos. */
1682 complain_overflow_signed, /* complain_on_overflow. */
1683 bfd_elf_generic_reloc, /* special_function. */
1684 "R_LARCH_TLS_DESC_HI20", /* name. */
1685 false, /* partial_inplace. */
1686 0, /* src_mask. */
1687 0x1ffffe0, /* dst_mask. */
1688 false, /* pcrel_offset. */
1689 BFD_RELOC_LARCH_TLS_DESC_HI20, /* bfd_reloc_code_real_type. */
1690 reloc_bits, /* adjust_reloc_bits. */
1691 "desc_hi20"), /* larch_reloc_type_name. */
1692
1693 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_LO12, /* type (116). */
1694 0, /* rightshift. */
1695 4, /* size. */
1696 12, /* bitsize. */
1697 false, /* pc_relative. */
1698 10, /* bitpos. */
1699 complain_overflow_signed, /* complain_on_overflow. */
1700 bfd_elf_generic_reloc, /* special_function. */
1701 "R_LARCH_TLS_DESC_LO12", /* name. */
1702 false, /* partial_inplace. */
1703 0, /* src_mask. */
1704 0x3ffc00, /* dst_mask. */
1705 false, /* pcrel_offset. */
1706 BFD_RELOC_LARCH_TLS_DESC_LO12, /* bfd_reloc_code_real_type. */
1707 reloc_bits, /* adjust_reloc_bits. */
1708 "desc_lo12"), /* larch_reloc_type_name. */
1709
1710 /* TLS_DESC64 LARGE ABS. */
1711 LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_LO20, /* type (117). */
1712 32, /* rightshift. */
1713 8, /* size. */
1714 20, /* bitsize. */
1715 false, /* pc_relative. */
1716 5, /* bitpos. */
1717 complain_overflow_signed, /* complain_on_overflow. */
1718 bfd_elf_generic_reloc, /* special_function. */
1719 "R_LARCH_TLS_DESC64_LO20", /* name. */
1720 false, /* partial_inplace. */
1721 0, /* src_mask. */
1722 0x1ffffe0, /* dst_mask. */
1723 false, /* pcrel_offset. */
1724 BFD_RELOC_LARCH_TLS_DESC64_LO20, /* bfd_reloc_code_real_type. */
1725 reloc_bits, /* adjust_reloc_bits. */
1726 "desc64_lo20"), /* larch_reloc_type_name. */
1727
1728 LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_HI12, /* type (118). */
1729 52, /* rightshift. */
1730 8, /* size. */
1731 12, /* bitsize. */
1732 false, /* pc_relative. */
1733 10, /* bitpos. */
1734 complain_overflow_signed, /* complain_on_overflow. */
1735 bfd_elf_generic_reloc, /* special_function. */
1736 "R_LARCH_TLS_DESC64_HI12", /* name. */
1737 false, /* partial_inplace. */
1738 0, /* src_mask. */
1739 0x3ffc00, /* dst_mask. */
1740 false, /* pcrel_offset. */
1741 BFD_RELOC_LARCH_TLS_DESC64_HI12, /* bfd_reloc_code_real_type. */
1742 reloc_bits, /* adjust_reloc_bits. */
1743 "desc64_hi12"), /* larch_reloc_type_name. */
1744
1745 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_LD, /* type (119). */
1746 0, /* rightshift. */
1747 4, /* size. */
1748 0, /* bitsize. */
1749 true, /* pc_relative. */
1750 0, /* bitpos. */
1751 complain_overflow_signed, /* complain_on_overflow. */
1752 bfd_elf_generic_reloc, /* special_function. */
1753 "R_LARCH_TLS_DESC_LD", /* name. */
1754 false, /* partial_inplace. */
1755 0, /* src_mask. */
1756 0, /* dst_mask. */
1757 false, /* pcrel_offset. */
1758 BFD_RELOC_LARCH_TLS_DESC_LD, /* bfd_reloc_code_real_type. */
1759 NULL, /* adjust_reloc_bits. */
1760 "desc_ld"), /* larch_reloc_type_name. */
1761
1762 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_CALL, /* type (120). */
1763 0, /* rightshift. */
1764 4, /* size. */
1765 0, /* bitsize. */
1766 false, /* pc_relative. */
1767 0, /* bitpos. */
1768 complain_overflow_dont, /* complain_on_overflow. */
1769 bfd_elf_generic_reloc, /* special_function. */
1770 "R_LARCH_TLS_DESC_CALL", /* name. */
1771 false, /* partial_inplace. */
1772 0, /* src_mask. */
1773 0, /* dst_mask. */
1774 false, /* pcrel_offset. */
1775 BFD_RELOC_LARCH_TLS_DESC_CALL, /* bfd_reloc_code_real_type. */
1776 NULL, /* adjust_reloc_bits. */
1777 "desc_call"), /* larch_reloc_type_name. */
1778
1779 LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20_R, /* type (121). */
1780 12, /* rightshift. */
1781 4, /* size. */
1782 20, /* bitsize. */
1783 false, /* pc_relative. */
1784 5, /* bitpos. */
1785 complain_overflow_signed, /* complain_on_overflow. */
1786 bfd_elf_generic_reloc, /* special_function. */
1787 "R_LARCH_TLS_LE_HI20_R", /* name. */
1788 false, /* partial_inplace. */
1789 0, /* src_mask. */
1790 0x1ffffe0, /* dst_mask. */
1791 false, /* pcrel_offset. */
1792 BFD_RELOC_LARCH_TLS_LE_HI20_R, /* bfd_reloc_code_real_type. */
1793 reloc_bits, /* adjust_reloc_bits. */
1794 "le_hi20_r"), /* larch_reloc_type_name. */
1795
1796 LOONGARCH_HOWTO (R_LARCH_TLS_LE_ADD_R, /* type (122). */
1797 0, /* rightshift. */
1798 0, /* size. */
1799 0, /* bitsize. */
1800 false, /* pc_relative. */
1801 0, /* bitpos. */
1802 complain_overflow_dont, /* complain_on_overflow. */
1803 bfd_elf_generic_reloc, /* special_function. */
1804 "R_LARCH_TLS_LE_ADD_R", /* name. */
1805 false, /* partial_inplace. */
1806 0, /* src_mask. */
1807 0, /* dst_mask. */
1808 false, /* pcrel_offset. */
1809 BFD_RELOC_LARCH_TLS_LE_ADD_R, /* bfd_reloc_code_real_type. */
1810 NULL, /* adjust_reloc_bits. */
1811 "le_add_r"), /* larch_reloc_type_name. */
1812
1813 LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12_R, /* type (123). */
1814 0, /* rightshift. */
1815 4, /* size. */
1816 12, /* bitsize. */
1817 false, /* pc_relative. */
1818 10, /* bitpos. */
1819 complain_overflow_signed, /* complain_on_overflow. */
1820 bfd_elf_generic_reloc, /* special_function. */
1821 "R_LARCH_TLS_LE_LO12_R", /* name. */
1822 false, /* partial_inplace. */
1823 0, /* src_mask. */
1824 0x3ffc00, /* dst_mask. */
1825 false, /* pcrel_offset. */
1826 BFD_RELOC_LARCH_TLS_LE_LO12_R, /* bfd_reloc_code_real_type. */
1827 reloc_bits, /* adjust_reloc_bits. */
1828 "le_lo12_r"), /* larch_reloc_type_name. */
1829
1830 /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2. */
1831 LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2, /* type (124). */
1832 2, /* rightshift. */
1833 4, /* size. */
1834 20, /* bitsize. */
1835 false, /* pc_relative. */
1836 5, /* bitpos. */
1837 complain_overflow_signed, /* complain_on_overflow. */
1838 bfd_elf_generic_reloc, /* special_function. */
1839 "R_LARCH_TLS_LD_PCREL20_S2", /* name. */
1840 false, /* partial_inplace. */
1841 0, /* src_mask. */
1842 0x1ffffe0, /* dst_mask. */
1843 true, /* pcrel_offset. */
1844 BFD_RELOC_LARCH_TLS_LD_PCREL20_S2, /* bfd_reloc_code_real_type. */
1845 reloc_sign_bits, /* adjust_reloc_bits. */
1846 "ld_pcrel_20"), /* larch_reloc_type_name. */
1847
1848 /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2. */
1849 LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2, /* type (125). */
1850 2, /* rightshift. */
1851 4, /* size. */
1852 20, /* bitsize. */
1853 false, /* pc_relative. */
1854 5, /* bitpos. */
1855 complain_overflow_signed, /* complain_on_overflow. */
1856 bfd_elf_generic_reloc, /* special_function. */
1857 "R_LARCH_TLS_GD_PCREL20_S2", /* name. */
1858 false, /* partial_inplace. */
1859 0, /* src_mask. */
1860 0x1ffffe0, /* dst_mask. */
1861 true, /* pcrel_offset. */
1862 BFD_RELOC_LARCH_TLS_GD_PCREL20_S2, /* bfd_reloc_code_real_type. */
1863 reloc_sign_bits, /* adjust_reloc_bits. */
1864 "gd_pcrel_20"), /* larch_reloc_type_name. */
1865
1866 /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to desc_pcrel20_s2. */
1867 LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2, /* type (126). */
1868 2, /* rightshift. */
1869 4, /* size. */
1870 20, /* bitsize. */
1871 false, /* pc_relative. */
1872 5, /* bitpos. */
1873 complain_overflow_signed, /* complain_on_overflow. */
1874 bfd_elf_generic_reloc, /* special_function. */
1875 "R_LARCH_TLS_DESC_PCREL20_S2", /* name. */
1876 false, /* partial_inplace. */
1877 0, /* src_mask. */
1878 0x1ffffe0, /* dst_mask. */
1879 true, /* pcrel_offset. */
1880 BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2, /* bfd_reloc_code_real_type. */
1881 reloc_sign_bits, /* adjust_reloc_bits. */
1882 "desc_pcrel_20"), /* larch_reloc_type_name. */
1883 };
1884
1885 reloc_howto_type *
loongarch_elf_rtype_to_howto(bfd * abfd,unsigned int r_type)1886 loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
1887 {
1888 if (r_type < R_LARCH_count)
1889 {
1890 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
1891 BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type);
1892 return &loongarch_howto_table[r_type].howto;
1893 }
1894
1895 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
1896 abfd, r_type);
1897 bfd_set_error (bfd_error_bad_value);
1898 return NULL;
1899 }
1900
1901 reloc_howto_type *
loongarch_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)1902 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
1903 {
1904 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1905 if (loongarch_howto_table[i].howto.name
1906 && strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0)
1907 return &loongarch_howto_table[i].howto;
1908
1909 (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"),
1910 abfd, r_name);
1911 bfd_set_error (bfd_error_bad_value);
1912 return NULL;
1913 }
1914
1915 /* Cost so much. */
1916 reloc_howto_type *
loongarch_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)1917 loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1918 bfd_reloc_code_real_type code)
1919 {
1920 BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
1921
1922 /* Fast search for new reloc types. */
1923 if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
1924 {
1925 BFD_ASSERT (BFD_RELOC_LARCH_RELAX - BFD_RELOC_LARCH_B16
1926 == R_LARCH_RELAX - R_LARCH_B16);
1927 loongarch_reloc_howto_type *ht;
1928 ht = &loongarch_howto_table[code - BFD_RELOC_LARCH_B16 + R_LARCH_B16];
1929 BFD_ASSERT (ht->bfd_type == code);
1930 return &ht->howto;
1931 }
1932
1933 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1934 if (loongarch_howto_table[i].bfd_type == code)
1935 return &loongarch_howto_table[i].howto;
1936
1937 (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"),
1938 abfd, code);
1939 bfd_set_error (bfd_error_bad_value);
1940 return NULL;
1941 }
1942
1943 bfd_reloc_code_real_type
loongarch_larch_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * l_r_name)1944 loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1945 const char *l_r_name)
1946 {
1947 for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
1948 {
1949 loongarch_reloc_howto_type *lht = &loongarch_howto_table[i];
1950 if ((NULL != lht->larch_reloc_type_name)
1951 && (0 == strcmp (lht->larch_reloc_type_name, l_r_name)))
1952 return lht->bfd_type;
1953 }
1954
1955 return BFD_RELOC_NONE;
1956 }
1957
1958
1959 /* Functions for reloc bits field.
1960 1. Signed extend *fix_val.
1961 2. Return false if overflow. */
1962
1963 #define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
1964 (~((((bfd_vma)0x1) << (bitsize)) - 1))
1965
1966 /* Adjust val to perform insn
1967 BFD_RELOC_LARCH_SOP_POP_32_S_10_5
1968 BFD_RELOC_LARCH_SOP_POP_32_S_10_12
1969 BFD_RELOC_LARCH_SOP_POP_32_U_10_12
1970 BFD_RELOC_LARCH_SOP_POP_32_S_10_16
1971 BFD_RELOC_LARCH_SOP_POP_32_S_5_20
1972 BFD_RELOC_LARCH_SOP_POP_32_U. */
1973
1974 static bool
reloc_bits(bfd * abfd ATTRIBUTE_UNUSED,reloc_howto_type * howto,bfd_vma * fix_val)1975 reloc_bits (bfd *abfd ATTRIBUTE_UNUSED,
1976 reloc_howto_type *howto,
1977 bfd_vma *fix_val)
1978 {
1979 bfd_signed_vma val = (bfd_signed_vma)(*fix_val);
1980 bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
1981
1982 val = val >> howto->rightshift;
1983
1984 /* Perform insn bits field. */
1985 val = val & mask;
1986 val <<= howto->bitpos;
1987
1988 *fix_val = (bfd_vma)val;
1989
1990 return true;
1991 }
1992
1993 static bool
reloc_sign_bits(bfd * abfd,reloc_howto_type * howto,bfd_vma * fix_val)1994 reloc_sign_bits (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val)
1995 {
1996 if (howto->complain_on_overflow != complain_overflow_signed)
1997 return false;
1998
1999 bfd_signed_vma val = (bfd_signed_vma)(*fix_val);
2000
2001 /* Check alignment. FIXME: if rightshift is not alingment. */
2002 if (howto->rightshift
2003 && (val & ((((bfd_signed_vma) 1) << howto->rightshift) - 1)))
2004 {
2005 /* The as passes NULL casued internal error, so it can not use _bfd_error_handler
2006 output details, ld is not affected. */
2007 if (abfd != NULL)
2008 {
2009 (*_bfd_error_handler) (_("%pB: relocation %s right shift %d error 0x%lx"),
2010 abfd, howto->name, howto->rightshift, (long) val);
2011 bfd_set_error (bfd_error_bad_value);
2012 }
2013 return false;
2014 }
2015
2016 bfd_signed_vma mask = ((bfd_signed_vma)0x1 << (howto->bitsize
2017 + howto->rightshift - 1)) - 1;
2018
2019 /* Positive number: high part is all 0;
2020 Negative number: if high part is not all 0, high part must be all 1.
2021 high part: from sign bit to highest bit. */
2022 if ((val & ~mask) && ((val & ~mask) != ~mask))
2023 {
2024 /* The as passes NULL casued internal error, so it can not use _bfd_error_handler
2025 output details, ld is not affected. */
2026 if (abfd != NULL)
2027 {
2028 (*_bfd_error_handler) (_("%pB: relocation %s overflow 0x%lx"),
2029 abfd, howto->name, (long) val);
2030 bfd_set_error (bfd_error_bad_value);
2031 }
2032 return false;
2033 }
2034
2035 val = val >> howto->rightshift;
2036 /* can delete? */
2037 mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
2038 val = val & mask;
2039
2040 switch (howto->type)
2041 {
2042 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
2043 case R_LARCH_B26:
2044 /* Perform insn bits field. 15:0<<10, 25:16>>16. */
2045 val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
2046 break;
2047 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
2048 case R_LARCH_B21:
2049 /* Perform insn bits field. 15:0<<10, 20:16>>16. */
2050 val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
2051 break;
2052 case R_LARCH_CALL36:
2053 /* 0x8000: If low 16-bit immediate greater than 0x7fff,
2054 it become to a negative number due to sign-extended,
2055 so the high part need to add 0x8000. */
2056 val = (((val + 0x8000) >> 16) << 5) | (((val & 0xffff) << 10) << 32);
2057 break;
2058 default:
2059 val <<= howto->bitpos;
2060 break;
2061 }
2062
2063 *fix_val = val;
2064 return true;
2065 }
2066
2067 bool
loongarch_adjust_reloc_bitsfield(bfd * abfd,reloc_howto_type * howto,bfd_vma * fix_val)2068 loongarch_adjust_reloc_bitsfield (bfd *abfd, reloc_howto_type *howto,
2069 bfd_vma *fix_val)
2070 {
2071 BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
2072 return ((loongarch_reloc_howto_type *)
2073 howto)->adjust_reloc_bits (abfd, howto, fix_val);
2074 }
2075
2076 static bfd_reloc_status_type
loongarch_elf_add_sub_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)2077 loongarch_elf_add_sub_reloc (bfd *abfd,
2078 arelent *reloc_entry,
2079 asymbol *symbol,
2080 void *data,
2081 asection *input_section,
2082 bfd *output_bfd,
2083 char **error_message ATTRIBUTE_UNUSED)
2084 {
2085 reloc_howto_type *howto = reloc_entry->howto;
2086 bfd_vma relocation;
2087
2088 if (output_bfd != NULL
2089 && (symbol->flags & BSF_SECTION_SYM) == 0
2090 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
2091 {
2092 reloc_entry->address += input_section->output_offset;
2093 return bfd_reloc_ok;
2094 }
2095
2096 if (output_bfd != NULL)
2097 return bfd_reloc_continue;
2098
2099 relocation = symbol->value + symbol->section->output_section->vma
2100 + symbol->section->output_offset + reloc_entry->addend;
2101
2102 bfd_size_type octets = reloc_entry->address
2103 * bfd_octets_per_byte (abfd, input_section);
2104 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
2105 input_section, octets))
2106 return bfd_reloc_outofrange;
2107
2108 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
2109 data + reloc_entry->address);
2110
2111 switch (howto->type)
2112 {
2113 case R_LARCH_ADD6:
2114 case R_LARCH_ADD8:
2115 case R_LARCH_ADD16:
2116 case R_LARCH_ADD32:
2117 case R_LARCH_ADD64:
2118 relocation = old_value + relocation;
2119 break;
2120
2121 case R_LARCH_SUB6:
2122 case R_LARCH_SUB8:
2123 case R_LARCH_SUB16:
2124 case R_LARCH_SUB32:
2125 case R_LARCH_SUB64:
2126 relocation = old_value - relocation;
2127 break;
2128 }
2129
2130 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
2131
2132 return bfd_reloc_ok;
2133 }
2134
2135 static bfd_reloc_status_type
loongarch_elf_add_sub_reloc_uleb128(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)2136 loongarch_elf_add_sub_reloc_uleb128 (bfd *abfd,
2137 arelent *reloc_entry,
2138 asymbol *symbol,
2139 void *data,
2140 asection *input_section,
2141 bfd *output_bfd,
2142 char **error_message ATTRIBUTE_UNUSED)
2143 {
2144 reloc_howto_type *howto = reloc_entry->howto;
2145 bfd_vma relocation;
2146
2147 if (output_bfd != NULL
2148 && (symbol->flags & BSF_SECTION_SYM) == 0
2149 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
2150 {
2151 reloc_entry->address += input_section->output_offset;
2152 return bfd_reloc_ok;
2153 }
2154
2155 if (output_bfd != NULL)
2156 return bfd_reloc_continue;
2157
2158 relocation = symbol->value + symbol->section->output_section->vma
2159 + symbol->section->output_offset + reloc_entry->addend;
2160
2161 bfd_size_type octets = reloc_entry->address
2162 * bfd_octets_per_byte (abfd, input_section);
2163 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
2164 input_section, octets))
2165 return bfd_reloc_outofrange;
2166
2167 unsigned int len = 0;
2168 bfd_byte *p = data + reloc_entry->address;
2169 bfd_vma old_value = _bfd_read_unsigned_leb128 (abfd, p, &len);
2170
2171 switch (howto->type)
2172 {
2173 case R_LARCH_ADD_ULEB128:
2174 relocation = old_value + relocation;
2175 break;
2176
2177 case R_LARCH_SUB_ULEB128:
2178 relocation = old_value - relocation;
2179 break;
2180 }
2181
2182 bfd_vma mask = (1 << (7 * len)) - 1;
2183 relocation = relocation & mask;
2184 loongarch_write_unsigned_leb128 (p, len, relocation);
2185 return bfd_reloc_ok;
2186 }
2187
2188 /* Write VALUE in uleb128 format to P.
2189 LEN is the uleb128 value length.
2190 Return a pointer to the byte following the last byte that was written. */
2191 bfd_byte *
loongarch_write_unsigned_leb128(bfd_byte * p,unsigned int len,bfd_vma value)2192 loongarch_write_unsigned_leb128 (bfd_byte *p, unsigned int len, bfd_vma value)
2193 {
2194 bfd_byte c;
2195 do
2196 {
2197 c = value & 0x7f;
2198 if (len > 1)
2199 c |= 0x80;
2200 *(p++) = c;
2201 value >>= 7;
2202 len--;
2203 }
2204 while (len);
2205 return p;
2206 }
2207
loongarch_get_uleb128_length(bfd_byte * buf)2208 int loongarch_get_uleb128_length (bfd_byte *buf)
2209 {
2210 unsigned int len = 0;
2211 _bfd_read_unsigned_leb128 (NULL, buf, &len);
2212 return len;
2213 }
2214