]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elfxx-riscv.c
Fix illegal memory access triggered by an attempt to disassemble a corrupt RISC-V...
[thirdparty/binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2021 Free Software Foundation, Inc.
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
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/riscv.h"
28 #include "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include "safe-ctype.h"
32 #include "cpu-riscv.h"
33
34 #define MINUS_ONE ((bfd_vma)0 - 1)
35
36 /* Special handler for ADD/SUB relocations that allows them to be filled out
37 both in the pre-linked and post-linked file. This is necessary to make
38 pre-linked debug info work, as due to linker relaxations we need to emit
39 relocations for the debug info. */
40 static bfd_reloc_status_type riscv_elf_add_sub_reloc
41 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
42
43 /* The relocation table used for SHT_RELA sections. */
44
45 static reloc_howto_type howto_table[] =
46 {
47 /* No relocation. */
48 HOWTO (R_RISCV_NONE, /* type */
49 0, /* rightshift */
50 3, /* size */
51 0, /* bitsize */
52 false, /* pc_relative */
53 0, /* bitpos */
54 complain_overflow_dont, /* complain_on_overflow */
55 bfd_elf_generic_reloc, /* special_function */
56 "R_RISCV_NONE", /* name */
57 false, /* partial_inplace */
58 0, /* src_mask */
59 0, /* dst_mask */
60 false), /* pcrel_offset */
61
62 /* 32 bit relocation. */
63 HOWTO (R_RISCV_32, /* type */
64 0, /* rightshift */
65 2, /* size */
66 32, /* bitsize */
67 false, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_dont, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_RISCV_32", /* name */
72 false, /* partial_inplace */
73 0, /* src_mask */
74 0xffffffff, /* dst_mask */
75 false), /* pcrel_offset */
76
77 /* 64 bit relocation. */
78 HOWTO (R_RISCV_64, /* type */
79 0, /* rightshift */
80 4, /* size */
81 64, /* bitsize */
82 false, /* pc_relative */
83 0, /* bitpos */
84 complain_overflow_dont, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_RISCV_64", /* name */
87 false, /* partial_inplace */
88 0, /* src_mask */
89 MINUS_ONE, /* dst_mask */
90 false), /* pcrel_offset */
91
92 /* Relocation against a local symbol in a shared object. */
93 HOWTO (R_RISCV_RELATIVE, /* type */
94 0, /* rightshift */
95 2, /* size */
96 32, /* bitsize */
97 false, /* pc_relative */
98 0, /* bitpos */
99 complain_overflow_dont, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_RISCV_RELATIVE", /* name */
102 false, /* partial_inplace */
103 0, /* src_mask */
104 0xffffffff, /* dst_mask */
105 false), /* pcrel_offset */
106
107 HOWTO (R_RISCV_COPY, /* type */
108 0, /* rightshift */
109 0, /* this one is variable size */
110 0, /* bitsize */
111 false, /* pc_relative */
112 0, /* bitpos */
113 complain_overflow_bitfield, /* complain_on_overflow */
114 bfd_elf_generic_reloc, /* special_function */
115 "R_RISCV_COPY", /* name */
116 false, /* partial_inplace */
117 0, /* src_mask */
118 0, /* dst_mask */
119 false), /* pcrel_offset */
120
121 HOWTO (R_RISCV_JUMP_SLOT, /* type */
122 0, /* rightshift */
123 4, /* size */
124 64, /* bitsize */
125 false, /* pc_relative */
126 0, /* bitpos */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_RISCV_JUMP_SLOT", /* name */
130 false, /* partial_inplace */
131 0, /* src_mask */
132 0, /* dst_mask */
133 false), /* pcrel_offset */
134
135 /* Dynamic TLS relocations. */
136 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
137 0, /* rightshift */
138 2, /* size */
139 32, /* bitsize */
140 false, /* pc_relative */
141 0, /* bitpos */
142 complain_overflow_dont, /* complain_on_overflow */
143 bfd_elf_generic_reloc, /* special_function */
144 "R_RISCV_TLS_DTPMOD32", /* name */
145 false, /* partial_inplace */
146 0, /* src_mask */
147 0xffffffff, /* dst_mask */
148 false), /* pcrel_offset */
149
150 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
151 0, /* rightshift */
152 4, /* size */
153 64, /* bitsize */
154 false, /* pc_relative */
155 0, /* bitpos */
156 complain_overflow_dont, /* complain_on_overflow */
157 bfd_elf_generic_reloc, /* special_function */
158 "R_RISCV_TLS_DTPMOD64", /* name */
159 false, /* partial_inplace */
160 0, /* src_mask */
161 MINUS_ONE, /* dst_mask */
162 false), /* pcrel_offset */
163
164 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
165 0, /* rightshift */
166 2, /* size */
167 32, /* bitsize */
168 false, /* pc_relative */
169 0, /* bitpos */
170 complain_overflow_dont, /* complain_on_overflow */
171 bfd_elf_generic_reloc, /* special_function */
172 "R_RISCV_TLS_DTPREL32", /* name */
173 true, /* partial_inplace */
174 0, /* src_mask */
175 0xffffffff, /* dst_mask */
176 false), /* pcrel_offset */
177
178 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
179 0, /* rightshift */
180 4, /* size */
181 64, /* bitsize */
182 false, /* pc_relative */
183 0, /* bitpos */
184 complain_overflow_dont, /* complain_on_overflow */
185 bfd_elf_generic_reloc, /* special_function */
186 "R_RISCV_TLS_DTPREL64", /* name */
187 true, /* partial_inplace */
188 0, /* src_mask */
189 MINUS_ONE, /* dst_mask */
190 false), /* pcrel_offset */
191
192 HOWTO (R_RISCV_TLS_TPREL32, /* type */
193 0, /* rightshift */
194 2, /* size */
195 32, /* bitsize */
196 false, /* pc_relative */
197 0, /* bitpos */
198 complain_overflow_dont, /* complain_on_overflow */
199 bfd_elf_generic_reloc, /* special_function */
200 "R_RISCV_TLS_TPREL32", /* name */
201 false, /* partial_inplace */
202 0, /* src_mask */
203 0xffffffff, /* dst_mask */
204 false), /* pcrel_offset */
205
206 HOWTO (R_RISCV_TLS_TPREL64, /* type */
207 0, /* rightshift */
208 4, /* size */
209 64, /* bitsize */
210 false, /* pc_relative */
211 0, /* bitpos */
212 complain_overflow_dont, /* complain_on_overflow */
213 bfd_elf_generic_reloc, /* special_function */
214 "R_RISCV_TLS_TPREL64", /* name */
215 false, /* partial_inplace */
216 0, /* src_mask */
217 MINUS_ONE, /* dst_mask */
218 false), /* pcrel_offset */
219
220 /* Reserved for future relocs that the dynamic linker must understand. */
221 EMPTY_HOWTO (12),
222 EMPTY_HOWTO (13),
223 EMPTY_HOWTO (14),
224 EMPTY_HOWTO (15),
225
226 /* 12-bit PC-relative branch offset. */
227 HOWTO (R_RISCV_BRANCH, /* type */
228 0, /* rightshift */
229 2, /* size */
230 32, /* bitsize */
231 true, /* pc_relative */
232 0, /* bitpos */
233 complain_overflow_signed, /* complain_on_overflow */
234 bfd_elf_generic_reloc, /* special_function */
235 "R_RISCV_BRANCH", /* name */
236 false, /* partial_inplace */
237 0, /* src_mask */
238 ENCODE_BTYPE_IMM (-1U), /* dst_mask */
239 true), /* pcrel_offset */
240
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL, /* type */
243 0, /* rightshift */
244 2, /* size */
245 32, /* bitsize */
246 true, /* pc_relative */
247 0, /* bitpos */
248 complain_overflow_dont, /* complain_on_overflow */
249 bfd_elf_generic_reloc, /* special_function */
250 "R_RISCV_JAL", /* name */
251 false, /* partial_inplace */
252 0, /* src_mask */
253 ENCODE_JTYPE_IMM (-1U), /* dst_mask */
254 true), /* pcrel_offset */
255
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL, /* type */
258 0, /* rightshift */
259 4, /* size */
260 64, /* bitsize */
261 true, /* pc_relative */
262 0, /* bitpos */
263 complain_overflow_dont, /* complain_on_overflow */
264 bfd_elf_generic_reloc, /* special_function */
265 "R_RISCV_CALL", /* name */
266 false, /* partial_inplace */
267 0, /* src_mask */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
269 /* dst_mask */
270 true), /* pcrel_offset */
271
272 /* Like R_RISCV_CALL, but not locally binding. */
273 HOWTO (R_RISCV_CALL_PLT, /* type */
274 0, /* rightshift */
275 4, /* size */
276 64, /* bitsize */
277 true, /* pc_relative */
278 0, /* bitpos */
279 complain_overflow_dont, /* complain_on_overflow */
280 bfd_elf_generic_reloc, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
282 false, /* partial_inplace */
283 0, /* src_mask */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
285 /* dst_mask */
286 true), /* pcrel_offset */
287
288 /* High 20 bits of 32-bit PC-relative GOT access. */
289 HOWTO (R_RISCV_GOT_HI20, /* type */
290 0, /* rightshift */
291 2, /* size */
292 32, /* bitsize */
293 true, /* pc_relative */
294 0, /* bitpos */
295 complain_overflow_dont, /* complain_on_overflow */
296 bfd_elf_generic_reloc, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
298 false, /* partial_inplace */
299 0, /* src_mask */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
301 false), /* pcrel_offset */
302
303 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
304 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
305 0, /* rightshift */
306 2, /* size */
307 32, /* bitsize */
308 true, /* pc_relative */
309 0, /* bitpos */
310 complain_overflow_dont, /* complain_on_overflow */
311 bfd_elf_generic_reloc, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
313 false, /* partial_inplace */
314 0, /* src_mask */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
316 false), /* pcrel_offset */
317
318 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
319 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
320 0, /* rightshift */
321 2, /* size */
322 32, /* bitsize */
323 true, /* pc_relative */
324 0, /* bitpos */
325 complain_overflow_dont, /* complain_on_overflow */
326 bfd_elf_generic_reloc, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
328 false, /* partial_inplace */
329 0, /* src_mask */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
331 false), /* pcrel_offset */
332
333 /* High 20 bits of 32-bit PC-relative reference. */
334 HOWTO (R_RISCV_PCREL_HI20, /* type */
335 0, /* rightshift */
336 2, /* size */
337 32, /* bitsize */
338 true, /* pc_relative */
339 0, /* bitpos */
340 complain_overflow_dont, /* complain_on_overflow */
341 bfd_elf_generic_reloc, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
343 false, /* partial_inplace */
344 0, /* src_mask */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
346 true), /* pcrel_offset */
347
348 /* Low 12 bits of a 32-bit PC-relative load or add. */
349 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
350 0, /* rightshift */
351 2, /* size */
352 32, /* bitsize */
353 false, /* pc_relative */
354 0, /* bitpos */
355 complain_overflow_dont, /* complain_on_overflow */
356 bfd_elf_generic_reloc, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
358 false, /* partial_inplace */
359 0, /* src_mask */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
361 false), /* pcrel_offset */
362
363 /* Low 12 bits of a 32-bit PC-relative store. */
364 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
365 0, /* rightshift */
366 2, /* size */
367 32, /* bitsize */
368 false, /* pc_relative */
369 0, /* bitpos */
370 complain_overflow_dont, /* complain_on_overflow */
371 bfd_elf_generic_reloc, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
373 false, /* partial_inplace */
374 0, /* src_mask */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
376 false), /* pcrel_offset */
377
378 /* High 20 bits of 32-bit absolute address. */
379 HOWTO (R_RISCV_HI20, /* type */
380 0, /* rightshift */
381 2, /* size */
382 32, /* bitsize */
383 false, /* pc_relative */
384 0, /* bitpos */
385 complain_overflow_dont, /* complain_on_overflow */
386 bfd_elf_generic_reloc, /* special_function */
387 "R_RISCV_HI20", /* name */
388 false, /* partial_inplace */
389 0, /* src_mask */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
391 false), /* pcrel_offset */
392
393 /* High 12 bits of 32-bit load or add. */
394 HOWTO (R_RISCV_LO12_I, /* type */
395 0, /* rightshift */
396 2, /* size */
397 32, /* bitsize */
398 false, /* pc_relative */
399 0, /* bitpos */
400 complain_overflow_dont, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_RISCV_LO12_I", /* name */
403 false, /* partial_inplace */
404 0, /* src_mask */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
406 false), /* pcrel_offset */
407
408 /* High 12 bits of 32-bit store. */
409 HOWTO (R_RISCV_LO12_S, /* type */
410 0, /* rightshift */
411 2, /* size */
412 32, /* bitsize */
413 false, /* pc_relative */
414 0, /* bitpos */
415 complain_overflow_dont, /* complain_on_overflow */
416 bfd_elf_generic_reloc, /* special_function */
417 "R_RISCV_LO12_S", /* name */
418 false, /* partial_inplace */
419 0, /* src_mask */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
421 false), /* pcrel_offset */
422
423 /* High 20 bits of TLS LE thread pointer offset. */
424 HOWTO (R_RISCV_TPREL_HI20, /* type */
425 0, /* rightshift */
426 2, /* size */
427 32, /* bitsize */
428 false, /* pc_relative */
429 0, /* bitpos */
430 complain_overflow_signed, /* complain_on_overflow */
431 bfd_elf_generic_reloc, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
433 true, /* partial_inplace */
434 0, /* src_mask */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
436 false), /* pcrel_offset */
437
438 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
439 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
440 0, /* rightshift */
441 2, /* size */
442 32, /* bitsize */
443 false, /* pc_relative */
444 0, /* bitpos */
445 complain_overflow_signed, /* complain_on_overflow */
446 bfd_elf_generic_reloc, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
448 false, /* partial_inplace */
449 0, /* src_mask */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
451 false), /* pcrel_offset */
452
453 /* Low 12 bits of TLS LE thread pointer offset for stores. */
454 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
455 0, /* rightshift */
456 2, /* size */
457 32, /* bitsize */
458 false, /* pc_relative */
459 0, /* bitpos */
460 complain_overflow_signed, /* complain_on_overflow */
461 bfd_elf_generic_reloc, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
463 false, /* partial_inplace */
464 0, /* src_mask */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
466 false), /* pcrel_offset */
467
468 /* TLS LE thread pointer usage. May be relaxed. */
469 HOWTO (R_RISCV_TPREL_ADD, /* type */
470 0, /* rightshift */
471 3, /* size */
472 0, /* bitsize */
473 false, /* pc_relative */
474 0, /* bitpos */
475 complain_overflow_dont, /* complain_on_overflow */
476 bfd_elf_generic_reloc, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
478 false, /* partial_inplace */
479 0, /* src_mask */
480 0, /* dst_mask */
481 false), /* pcrel_offset */
482
483 /* 8-bit in-place addition, for local label subtraction. */
484 HOWTO (R_RISCV_ADD8, /* type */
485 0, /* rightshift */
486 0, /* size */
487 8, /* bitsize */
488 false, /* pc_relative */
489 0, /* bitpos */
490 complain_overflow_dont, /* complain_on_overflow */
491 riscv_elf_add_sub_reloc, /* special_function */
492 "R_RISCV_ADD8", /* name */
493 false, /* partial_inplace */
494 0, /* src_mask */
495 0xff, /* dst_mask */
496 false), /* pcrel_offset */
497
498 /* 16-bit in-place addition, for local label subtraction. */
499 HOWTO (R_RISCV_ADD16, /* type */
500 0, /* rightshift */
501 1, /* size */
502 16, /* bitsize */
503 false, /* pc_relative */
504 0, /* bitpos */
505 complain_overflow_dont, /* complain_on_overflow */
506 riscv_elf_add_sub_reloc, /* special_function */
507 "R_RISCV_ADD16", /* name */
508 false, /* partial_inplace */
509 0, /* src_mask */
510 0xffff, /* dst_mask */
511 false), /* pcrel_offset */
512
513 /* 32-bit in-place addition, for local label subtraction. */
514 HOWTO (R_RISCV_ADD32, /* type */
515 0, /* rightshift */
516 2, /* size */
517 32, /* bitsize */
518 false, /* pc_relative */
519 0, /* bitpos */
520 complain_overflow_dont, /* complain_on_overflow */
521 riscv_elf_add_sub_reloc, /* special_function */
522 "R_RISCV_ADD32", /* name */
523 false, /* partial_inplace */
524 0, /* src_mask */
525 0xffffffff, /* dst_mask */
526 false), /* pcrel_offset */
527
528 /* 64-bit in-place addition, for local label subtraction. */
529 HOWTO (R_RISCV_ADD64, /* type */
530 0, /* rightshift */
531 4, /* size */
532 64, /* bitsize */
533 false, /* pc_relative */
534 0, /* bitpos */
535 complain_overflow_dont, /* complain_on_overflow */
536 riscv_elf_add_sub_reloc, /* special_function */
537 "R_RISCV_ADD64", /* name */
538 false, /* partial_inplace */
539 0, /* src_mask */
540 MINUS_ONE, /* dst_mask */
541 false), /* pcrel_offset */
542
543 /* 8-bit in-place addition, for local label subtraction. */
544 HOWTO (R_RISCV_SUB8, /* type */
545 0, /* rightshift */
546 0, /* size */
547 8, /* bitsize */
548 false, /* pc_relative */
549 0, /* bitpos */
550 complain_overflow_dont, /* complain_on_overflow */
551 riscv_elf_add_sub_reloc, /* special_function */
552 "R_RISCV_SUB8", /* name */
553 false, /* partial_inplace */
554 0, /* src_mask */
555 0xff, /* dst_mask */
556 false), /* pcrel_offset */
557
558 /* 16-bit in-place addition, for local label subtraction. */
559 HOWTO (R_RISCV_SUB16, /* type */
560 0, /* rightshift */
561 1, /* size */
562 16, /* bitsize */
563 false, /* pc_relative */
564 0, /* bitpos */
565 complain_overflow_dont, /* complain_on_overflow */
566 riscv_elf_add_sub_reloc, /* special_function */
567 "R_RISCV_SUB16", /* name */
568 false, /* partial_inplace */
569 0, /* src_mask */
570 0xffff, /* dst_mask */
571 false), /* pcrel_offset */
572
573 /* 32-bit in-place addition, for local label subtraction. */
574 HOWTO (R_RISCV_SUB32, /* type */
575 0, /* rightshift */
576 2, /* size */
577 32, /* bitsize */
578 false, /* pc_relative */
579 0, /* bitpos */
580 complain_overflow_dont, /* complain_on_overflow */
581 riscv_elf_add_sub_reloc, /* special_function */
582 "R_RISCV_SUB32", /* name */
583 false, /* partial_inplace */
584 0, /* src_mask */
585 0xffffffff, /* dst_mask */
586 false), /* pcrel_offset */
587
588 /* 64-bit in-place addition, for local label subtraction. */
589 HOWTO (R_RISCV_SUB64, /* type */
590 0, /* rightshift */
591 4, /* size */
592 64, /* bitsize */
593 false, /* pc_relative */
594 0, /* bitpos */
595 complain_overflow_dont, /* complain_on_overflow */
596 riscv_elf_add_sub_reloc, /* special_function */
597 "R_RISCV_SUB64", /* name */
598 false, /* partial_inplace */
599 0, /* src_mask */
600 MINUS_ONE, /* dst_mask */
601 false), /* pcrel_offset */
602
603 /* GNU extension to record C++ vtable hierarchy */
604 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
605 0, /* rightshift */
606 4, /* size */
607 0, /* bitsize */
608 false, /* pc_relative */
609 0, /* bitpos */
610 complain_overflow_dont, /* complain_on_overflow */
611 NULL, /* special_function */
612 "R_RISCV_GNU_VTINHERIT", /* name */
613 false, /* partial_inplace */
614 0, /* src_mask */
615 0, /* dst_mask */
616 false), /* pcrel_offset */
617
618 /* GNU extension to record C++ vtable member usage */
619 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
620 0, /* rightshift */
621 4, /* size */
622 0, /* bitsize */
623 false, /* pc_relative */
624 0, /* bitpos */
625 complain_overflow_dont, /* complain_on_overflow */
626 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
627 "R_RISCV_GNU_VTENTRY", /* name */
628 false, /* partial_inplace */
629 0, /* src_mask */
630 0, /* dst_mask */
631 false), /* pcrel_offset */
632
633 /* Indicates an alignment statement. The addend field encodes how many
634 bytes of NOPs follow the statement. The desired alignment is the
635 addend rounded up to the next power of two. */
636 HOWTO (R_RISCV_ALIGN, /* type */
637 0, /* rightshift */
638 3, /* size */
639 0, /* bitsize */
640 false, /* pc_relative */
641 0, /* bitpos */
642 complain_overflow_dont, /* complain_on_overflow */
643 bfd_elf_generic_reloc, /* special_function */
644 "R_RISCV_ALIGN", /* name */
645 false, /* partial_inplace */
646 0, /* src_mask */
647 0, /* dst_mask */
648 false), /* pcrel_offset */
649
650 /* 8-bit PC-relative branch offset. */
651 HOWTO (R_RISCV_RVC_BRANCH, /* type */
652 0, /* rightshift */
653 1, /* size */
654 16, /* bitsize */
655 true, /* pc_relative */
656 0, /* bitpos */
657 complain_overflow_signed, /* complain_on_overflow */
658 bfd_elf_generic_reloc, /* special_function */
659 "R_RISCV_RVC_BRANCH", /* name */
660 false, /* partial_inplace */
661 0, /* src_mask */
662 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */
663 true), /* pcrel_offset */
664
665 /* 11-bit PC-relative jump offset. */
666 HOWTO (R_RISCV_RVC_JUMP, /* type */
667 0, /* rightshift */
668 1, /* size */
669 16, /* bitsize */
670 true, /* pc_relative */
671 0, /* bitpos */
672 complain_overflow_dont, /* complain_on_overflow */
673 bfd_elf_generic_reloc, /* special_function */
674 "R_RISCV_RVC_JUMP", /* name */
675 false, /* partial_inplace */
676 0, /* src_mask */
677 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */
678 true), /* pcrel_offset */
679
680 /* High 6 bits of 18-bit absolute address. */
681 HOWTO (R_RISCV_RVC_LUI, /* type */
682 0, /* rightshift */
683 1, /* size */
684 16, /* bitsize */
685 false, /* pc_relative */
686 0, /* bitpos */
687 complain_overflow_dont, /* complain_on_overflow */
688 bfd_elf_generic_reloc, /* special_function */
689 "R_RISCV_RVC_LUI", /* name */
690 false, /* partial_inplace */
691 0, /* src_mask */
692 ENCODE_CITYPE_IMM (-1U), /* dst_mask */
693 false), /* pcrel_offset */
694
695 /* GP-relative load. */
696 HOWTO (R_RISCV_GPREL_I, /* type */
697 0, /* rightshift */
698 2, /* size */
699 32, /* bitsize */
700 false, /* pc_relative */
701 0, /* bitpos */
702 complain_overflow_dont, /* complain_on_overflow */
703 bfd_elf_generic_reloc, /* special_function */
704 "R_RISCV_GPREL_I", /* name */
705 false, /* partial_inplace */
706 0, /* src_mask */
707 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
708 false), /* pcrel_offset */
709
710 /* GP-relative store. */
711 HOWTO (R_RISCV_GPREL_S, /* type */
712 0, /* rightshift */
713 2, /* size */
714 32, /* bitsize */
715 false, /* pc_relative */
716 0, /* bitpos */
717 complain_overflow_dont, /* complain_on_overflow */
718 bfd_elf_generic_reloc, /* special_function */
719 "R_RISCV_GPREL_S", /* name */
720 false, /* partial_inplace */
721 0, /* src_mask */
722 ENCODE_STYPE_IMM (-1U), /* dst_mask */
723 false), /* pcrel_offset */
724
725 /* TP-relative TLS LE load. */
726 HOWTO (R_RISCV_TPREL_I, /* type */
727 0, /* rightshift */
728 2, /* size */
729 32, /* bitsize */
730 false, /* pc_relative */
731 0, /* bitpos */
732 complain_overflow_signed, /* complain_on_overflow */
733 bfd_elf_generic_reloc, /* special_function */
734 "R_RISCV_TPREL_I", /* name */
735 false, /* partial_inplace */
736 0, /* src_mask */
737 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
738 false), /* pcrel_offset */
739
740 /* TP-relative TLS LE store. */
741 HOWTO (R_RISCV_TPREL_S, /* type */
742 0, /* rightshift */
743 2, /* size */
744 32, /* bitsize */
745 false, /* pc_relative */
746 0, /* bitpos */
747 complain_overflow_signed, /* complain_on_overflow */
748 bfd_elf_generic_reloc, /* special_function */
749 "R_RISCV_TPREL_S", /* name */
750 false, /* partial_inplace */
751 0, /* src_mask */
752 ENCODE_STYPE_IMM (-1U), /* dst_mask */
753 false), /* pcrel_offset */
754
755 /* The paired relocation may be relaxed. */
756 HOWTO (R_RISCV_RELAX, /* type */
757 0, /* rightshift */
758 3, /* size */
759 0, /* bitsize */
760 false, /* pc_relative */
761 0, /* bitpos */
762 complain_overflow_dont, /* complain_on_overflow */
763 bfd_elf_generic_reloc, /* special_function */
764 "R_RISCV_RELAX", /* name */
765 false, /* partial_inplace */
766 0, /* src_mask */
767 0, /* dst_mask */
768 false), /* pcrel_offset */
769
770 /* 6-bit in-place addition, for local label subtraction. */
771 HOWTO (R_RISCV_SUB6, /* type */
772 0, /* rightshift */
773 0, /* size */
774 8, /* bitsize */
775 false, /* pc_relative */
776 0, /* bitpos */
777 complain_overflow_dont, /* complain_on_overflow */
778 riscv_elf_add_sub_reloc, /* special_function */
779 "R_RISCV_SUB6", /* name */
780 false, /* partial_inplace */
781 0, /* src_mask */
782 0x3f, /* dst_mask */
783 false), /* pcrel_offset */
784
785 /* 6-bit in-place setting, for local label subtraction. */
786 HOWTO (R_RISCV_SET6, /* type */
787 0, /* rightshift */
788 0, /* size */
789 8, /* bitsize */
790 false, /* pc_relative */
791 0, /* bitpos */
792 complain_overflow_dont, /* complain_on_overflow */
793 bfd_elf_generic_reloc, /* special_function */
794 "R_RISCV_SET6", /* name */
795 false, /* partial_inplace */
796 0, /* src_mask */
797 0x3f, /* dst_mask */
798 false), /* pcrel_offset */
799
800 /* 8-bit in-place setting, for local label subtraction. */
801 HOWTO (R_RISCV_SET8, /* type */
802 0, /* rightshift */
803 0, /* size */
804 8, /* bitsize */
805 false, /* pc_relative */
806 0, /* bitpos */
807 complain_overflow_dont, /* complain_on_overflow */
808 bfd_elf_generic_reloc, /* special_function */
809 "R_RISCV_SET8", /* name */
810 false, /* partial_inplace */
811 0, /* src_mask */
812 0xff, /* dst_mask */
813 false), /* pcrel_offset */
814
815 /* 16-bit in-place setting, for local label subtraction. */
816 HOWTO (R_RISCV_SET16, /* type */
817 0, /* rightshift */
818 1, /* size */
819 16, /* bitsize */
820 false, /* pc_relative */
821 0, /* bitpos */
822 complain_overflow_dont, /* complain_on_overflow */
823 bfd_elf_generic_reloc, /* special_function */
824 "R_RISCV_SET16", /* name */
825 false, /* partial_inplace */
826 0, /* src_mask */
827 0xffff, /* dst_mask */
828 false), /* pcrel_offset */
829
830 /* 32-bit in-place setting, for local label subtraction. */
831 HOWTO (R_RISCV_SET32, /* type */
832 0, /* rightshift */
833 2, /* size */
834 32, /* bitsize */
835 false, /* pc_relative */
836 0, /* bitpos */
837 complain_overflow_dont, /* complain_on_overflow */
838 bfd_elf_generic_reloc, /* special_function */
839 "R_RISCV_SET32", /* name */
840 false, /* partial_inplace */
841 0, /* src_mask */
842 0xffffffff, /* dst_mask */
843 false), /* pcrel_offset */
844
845 /* 32-bit PC relative. */
846 HOWTO (R_RISCV_32_PCREL, /* type */
847 0, /* rightshift */
848 2, /* size */
849 32, /* bitsize */
850 true, /* pc_relative */
851 0, /* bitpos */
852 complain_overflow_dont, /* complain_on_overflow */
853 bfd_elf_generic_reloc, /* special_function */
854 "R_RISCV_32_PCREL", /* name */
855 false, /* partial_inplace */
856 0, /* src_mask */
857 0xffffffff, /* dst_mask */
858 false), /* pcrel_offset */
859
860 /* Relocation against a local ifunc symbol in a shared object. */
861 HOWTO (R_RISCV_IRELATIVE, /* type */
862 0, /* rightshift */
863 2, /* size */
864 32, /* bitsize */
865 false, /* pc_relative */
866 0, /* bitpos */
867 complain_overflow_dont, /* complain_on_overflow */
868 bfd_elf_generic_reloc, /* special_function */
869 "R_RISCV_IRELATIVE", /* name */
870 false, /* partial_inplace */
871 0, /* src_mask */
872 0xffffffff, /* dst_mask */
873 false), /* pcrel_offset */
874 };
875
876 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
877 struct elf_reloc_map
878 {
879 bfd_reloc_code_real_type bfd_val;
880 enum elf_riscv_reloc_type elf_val;
881 };
882
883 static const struct elf_reloc_map riscv_reloc_map[] =
884 {
885 { BFD_RELOC_NONE, R_RISCV_NONE },
886 { BFD_RELOC_32, R_RISCV_32 },
887 { BFD_RELOC_64, R_RISCV_64 },
888 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
889 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
890 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
891 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
892 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
893 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
894 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
895 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
896 { BFD_RELOC_CTOR, R_RISCV_64 },
897 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
898 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
899 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
900 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
901 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
902 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
903 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
904 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
905 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
906 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
907 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
908 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
909 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
910 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
911 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
912 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
913 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
914 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
915 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
916 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
917 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
918 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
919 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
920 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
921 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
922 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
923 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
924 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
925 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
926 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
927 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
928 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
929 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
930 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
931 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
932 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
933 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
934 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
935 };
936
937 /* Given a BFD reloc type, return a howto structure. */
938
939 reloc_howto_type *
940 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
941 bfd_reloc_code_real_type code)
942 {
943 unsigned int i;
944
945 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
946 if (riscv_reloc_map[i].bfd_val == code)
947 return &howto_table[(int) riscv_reloc_map[i].elf_val];
948
949 bfd_set_error (bfd_error_bad_value);
950 return NULL;
951 }
952
953 reloc_howto_type *
954 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
955 {
956 unsigned int i;
957
958 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
959 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
960 return &howto_table[i];
961
962 return NULL;
963 }
964
965 reloc_howto_type *
966 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
967 {
968 if (r_type >= ARRAY_SIZE (howto_table))
969 {
970 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
971 abfd, r_type);
972 bfd_set_error (bfd_error_bad_value);
973 return NULL;
974 }
975 return &howto_table[r_type];
976 }
977
978 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
979
980 static bfd_reloc_status_type
981 riscv_elf_add_sub_reloc (bfd *abfd,
982 arelent *reloc_entry,
983 asymbol *symbol,
984 void *data,
985 asection *input_section,
986 bfd *output_bfd,
987 char **error_message ATTRIBUTE_UNUSED)
988 {
989 reloc_howto_type *howto = reloc_entry->howto;
990 bfd_vma relocation;
991
992 if (output_bfd != NULL
993 && (symbol->flags & BSF_SECTION_SYM) == 0
994 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
995 {
996 reloc_entry->address += input_section->output_offset;
997 return bfd_reloc_ok;
998 }
999
1000 if (output_bfd != NULL)
1001 return bfd_reloc_continue;
1002
1003 relocation = symbol->value + symbol->section->output_section->vma
1004 + symbol->section->output_offset + reloc_entry->addend;
1005
1006 bfd_size_type octets = reloc_entry->address
1007 * bfd_octets_per_byte (abfd, input_section);
1008 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
1009 input_section, octets))
1010 return bfd_reloc_outofrange;
1011
1012 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1013 data + reloc_entry->address);
1014
1015 switch (howto->type)
1016 {
1017 case R_RISCV_ADD8:
1018 case R_RISCV_ADD16:
1019 case R_RISCV_ADD32:
1020 case R_RISCV_ADD64:
1021 relocation = old_value + relocation;
1022 break;
1023 case R_RISCV_SUB6:
1024 case R_RISCV_SUB8:
1025 case R_RISCV_SUB16:
1026 case R_RISCV_SUB32:
1027 case R_RISCV_SUB64:
1028 relocation = old_value - relocation;
1029 break;
1030 }
1031 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1032
1033 return bfd_reloc_ok;
1034 }
1035
1036 /* Always add the IMPLICIT for the SUBSET. */
1037
1038 static bool
1039 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1040 riscv_subset_t *subset ATTRIBUTE_UNUSED)
1041 {
1042 return true;
1043 }
1044
1045 /* Add the IMPLICIT only when the version of SUBSET less than 2.1. */
1046
1047 static bool
1048 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1049 riscv_subset_t *subset)
1050 {
1051 return (subset->major_version < 2
1052 || (subset->major_version == 2
1053 && subset->minor_version < 1));
1054 }
1055
1056 /* Record all implicit information for the subsets. */
1057 struct riscv_implicit_subset
1058 {
1059 const char *subset_name;
1060 const char *implicit_name;
1061 /* A function to determine if we need to add the implicit subset. */
1062 bool (*check_func) (const char *, riscv_subset_t *);
1063 };
1064 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1065 {
1066 {"e", "i", check_implicit_always},
1067 {"i", "zicsr", check_implicit_for_i},
1068 {"i", "zifencei", check_implicit_for_i},
1069 {"g", "zicsr", check_implicit_always},
1070 {"g", "zifencei", check_implicit_always},
1071 {"q", "d", check_implicit_always},
1072 {"d", "f", check_implicit_always},
1073 {"f", "zicsr", check_implicit_always},
1074 {NULL, NULL, NULL}
1075 };
1076
1077 /* Lists of prefixed class extensions that binutils should know about.
1078 Whether or not a particular entry is in these lists will dictate if
1079 gas/ld will accept its presence in the architecture string.
1080
1081 Please add the extensions to the lists in lower case. However, keep
1082 these subsets in alphabetical order in these tables is recommended,
1083 although there is no impact on the current implementation. */
1084
1085 static const char * const riscv_std_z_ext_strtab[] =
1086 {
1087 "zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
1088 };
1089
1090 static const char * const riscv_std_s_ext_strtab[] =
1091 {
1092 NULL
1093 };
1094
1095 static const char * const riscv_std_h_ext_strtab[] =
1096 {
1097 NULL
1098 };
1099
1100 static const char * const riscv_std_zxm_ext_strtab[] =
1101 {
1102 NULL
1103 };
1104
1105 /* ISA extension prefixed name class. Must define them in parsing order. */
1106 enum riscv_prefix_ext_class
1107 {
1108 RV_ISA_CLASS_Z = 1,
1109 RV_ISA_CLASS_S,
1110 RV_ISA_CLASS_H,
1111 RV_ISA_CLASS_ZXM,
1112 RV_ISA_CLASS_X,
1113 RV_ISA_CLASS_UNKNOWN
1114 };
1115
1116 /* Record the strings of the prefixed extensions, and their corresponding
1117 classes. The more letters of the prefix string, the more forward it must
1118 be defined. Otherwise, the riscv_get_prefix_class will map it to the
1119 wrong classes. */
1120 struct riscv_parse_prefix_config
1121 {
1122 /* Class of the extension. */
1123 enum riscv_prefix_ext_class class;
1124
1125 /* Prefix string for error printing and internal parser usage. */
1126 const char *prefix;
1127 };
1128 static const struct riscv_parse_prefix_config parse_config[] =
1129 {
1130 {RV_ISA_CLASS_ZXM, "zxm"},
1131 {RV_ISA_CLASS_Z, "z"},
1132 {RV_ISA_CLASS_S, "s"},
1133 {RV_ISA_CLASS_H, "h"},
1134 {RV_ISA_CLASS_X, "x"},
1135 {RV_ISA_CLASS_UNKNOWN, NULL}
1136 };
1137
1138 /* Get the prefixed name class for the extensions, the class also
1139 means the order of the prefixed extensions. */
1140
1141 static enum riscv_prefix_ext_class
1142 riscv_get_prefix_class (const char *arch)
1143 {
1144 int i = 0;
1145 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1146 {
1147 if (strncmp (arch, parse_config[i].prefix,
1148 strlen (parse_config[i].prefix)) == 0)
1149 return parse_config[i].class;
1150 i++;
1151 }
1152 return RV_ISA_CLASS_UNKNOWN;
1153 }
1154
1155 /* Check KNOWN_EXTS to see if the EXT is supported. */
1156
1157 static bool
1158 riscv_known_prefixed_ext (const char *ext,
1159 const char *const *known_exts)
1160 {
1161 size_t i;
1162 for (i = 0; known_exts[i]; ++i)
1163 if (strcmp (ext, known_exts[i]) == 0)
1164 return true;
1165 return false;
1166 }
1167
1168 /* Check whether the prefixed extension is valid or not. Return
1169 true if valid, otehrwise return false. */
1170
1171 static bool
1172 riscv_valid_prefixed_ext (const char *ext)
1173 {
1174 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1175 switch (class)
1176 {
1177 case RV_ISA_CLASS_Z:
1178 return riscv_known_prefixed_ext (ext, riscv_std_z_ext_strtab);
1179 case RV_ISA_CLASS_ZXM:
1180 return riscv_known_prefixed_ext (ext, riscv_std_zxm_ext_strtab);
1181 case RV_ISA_CLASS_S:
1182 return riscv_known_prefixed_ext (ext, riscv_std_s_ext_strtab);
1183 case RV_ISA_CLASS_H:
1184 return riscv_known_prefixed_ext (ext, riscv_std_h_ext_strtab);
1185 case RV_ISA_CLASS_X:
1186 /* Only the single x is invalid. */
1187 if (strcmp (ext, "x") != 0)
1188 return true;
1189 default:
1190 break;
1191 }
1192 return false;
1193 }
1194
1195 /* Array is used to compare the orders of standard extensions quickly. */
1196 static int riscv_ext_order[26] = {0};
1197
1198 /* Init the riscv_ext_order array. */
1199
1200 static void
1201 riscv_init_ext_order (void)
1202 {
1203 static bool inited = false;
1204 const char *std_base_exts = "eig";
1205 const char *std_remain_exts = riscv_supported_std_ext ();
1206 const char *ext;
1207 int order;
1208
1209 if (inited)
1210 return;
1211
1212 /* The orders of all standard extensions are positive. */
1213 order = 1;
1214
1215 /* Init the standard base extensions first. */
1216 for (ext = std_base_exts; *ext; ext++)
1217 riscv_ext_order[(*ext - 'a')] = order++;
1218
1219 /* Init the standard remaining extensions. */
1220 for (ext = std_remain_exts; *ext; ext++)
1221 riscv_ext_order[(*ext - 'a')] = order++;
1222
1223 /* Some of the prefixed keyword are not single letter, so we set
1224 their prefixed orders in the riscv_compare_subsets directly,
1225 not through the riscv_ext_order. */
1226
1227 inited = true;
1228 }
1229
1230 /* Similar to the strcmp. It returns an integer less than, equal to,
1231 or greater than zero if `subset2` is found, respectively, to be less
1232 than, to match, or be greater than `subset1`.
1233
1234 The order values,
1235 Zero: Preserved keywords.
1236 Positive number: Standard extensions.
1237 Negative number: Prefixed keywords. */
1238
1239 int
1240 riscv_compare_subsets (const char *subset1, const char *subset2)
1241 {
1242 int order1 = riscv_ext_order[(*subset1 - 'a')];
1243 int order2 = riscv_ext_order[(*subset2 - 'a')];
1244
1245 /* Compare the standard extension first. */
1246 if (order1 > 0 && order2 > 0)
1247 return order1 - order2;
1248
1249 /* Set the prefixed orders to negative numbers. */
1250 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1251 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1252
1253 if (class1 != RV_ISA_CLASS_UNKNOWN)
1254 order1 = - (int) class1;
1255 if (class2 != RV_ISA_CLASS_UNKNOWN)
1256 order2 = - (int) class2;
1257
1258 if (order1 == order2)
1259 {
1260 /* Compare the standard addition z extensions. */
1261 if (class1 == RV_ISA_CLASS_Z)
1262 {
1263 order1 = riscv_ext_order[(*++subset1 - 'a')];
1264 order2 = riscv_ext_order[(*++subset2 - 'a')];
1265 if (order1 != order2)
1266 return order1 - order2;
1267 }
1268 return strcasecmp (++subset1, ++subset2);
1269 }
1270
1271 return order2 - order1;
1272 }
1273
1274 /* Find subset in the list. Return TRUE and set `current` to the subset
1275 if it is found. Otherwise, return FALSE and set `current` to the place
1276 where we should insert the subset. However, return FALSE with the NULL
1277 `current` means we should insert the subset at the head of subset list,
1278 if needed. */
1279
1280 bool
1281 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1282 const char *subset,
1283 riscv_subset_t **current)
1284 {
1285 riscv_subset_t *s, *pre_s = NULL;
1286
1287 /* If the subset is added in order, then just add it at the tail. */
1288 if (subset_list->tail != NULL
1289 && riscv_compare_subsets (subset_list->tail->name, subset) < 0)
1290 {
1291 *current = subset_list->tail;
1292 return false;
1293 }
1294
1295 for (s = subset_list->head;
1296 s != NULL;
1297 pre_s = s, s = s->next)
1298 {
1299 int cmp = riscv_compare_subsets (s->name, subset);
1300 if (cmp == 0)
1301 {
1302 *current = s;
1303 return true;
1304 }
1305 else if (cmp > 0)
1306 break;
1307 }
1308 *current = pre_s;
1309
1310 return false;
1311 }
1312
1313 /* Add the extension to the subset list. Search the
1314 list first, and then find the right place to add. */
1315
1316 void
1317 riscv_add_subset (riscv_subset_list_t *subset_list,
1318 const char *subset,
1319 int major,
1320 int minor)
1321 {
1322 riscv_subset_t *current, *new;
1323
1324 if (riscv_lookup_subset (subset_list, subset, &current))
1325 return;
1326
1327 new = xmalloc (sizeof *new);
1328 new->name = xstrdup (subset);
1329 new->major_version = major;
1330 new->minor_version = minor;
1331 new->next = NULL;
1332
1333 if (current != NULL)
1334 {
1335 new->next = current->next;
1336 current->next = new;
1337 }
1338 else
1339 {
1340 new->next = subset_list->head;
1341 subset_list->head = new;
1342 }
1343
1344 if (new->next == NULL)
1345 subset_list->tail = new;
1346 }
1347
1348 /* Find the default versions for the extension before adding them to
1349 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1350 Afterwards, report errors if we can not find their default versions. */
1351
1352 static void
1353 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1354 const char *subset,
1355 int major,
1356 int minor,
1357 bool implicit)
1358 {
1359 int major_version = major;
1360 int minor_version = minor;
1361
1362 if ((major_version == RISCV_UNKNOWN_VERSION
1363 || minor_version == RISCV_UNKNOWN_VERSION)
1364 && rps->get_default_version != NULL)
1365 rps->get_default_version (subset, &major_version, &minor_version);
1366
1367 /* We don't care the versions of the implicit extensions. */
1368 if (!implicit
1369 && (major_version == RISCV_UNKNOWN_VERSION
1370 || minor_version == RISCV_UNKNOWN_VERSION))
1371 {
1372 if (subset[0] == 'x')
1373 rps->error_handler
1374 (_("x ISA extension `%s' must be set with the versions"),
1375 subset);
1376 else
1377 rps->error_handler
1378 (_("cannot find default versions of the ISA extension `%s'"),
1379 subset);
1380 return;
1381 }
1382
1383 riscv_add_subset (rps->subset_list, subset,
1384 major_version, minor_version);
1385 }
1386
1387 /* Release subset list. */
1388
1389 void
1390 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1391 {
1392 while (subset_list->head != NULL)
1393 {
1394 riscv_subset_t *next = subset_list->head->next;
1395 free ((void *)subset_list->head->name);
1396 free (subset_list->head);
1397 subset_list->head = next;
1398 }
1399
1400 subset_list->tail = NULL;
1401 }
1402
1403 /* Parsing extension version.
1404
1405 Return Value:
1406 Points to the end of version
1407
1408 Arguments:
1409 `rps`: Hooks and status for parsing extensions.
1410 `arch`: Full ISA string.
1411 `p`: Curent parsing position.
1412 `major_version`: Parsed major version.
1413 `minor_version`: Parsed minor version.
1414 `std_ext_p`: True if parsing standard extension. */
1415
1416 static const char *
1417 riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1418 const char *arch,
1419 const char *p,
1420 int *major_version,
1421 int *minor_version,
1422 bool std_ext_p)
1423 {
1424 bool major_p = true;
1425 int version = 0;
1426 char np;
1427
1428 *major_version = 0;
1429 *minor_version = 0;
1430 for (; *p; ++p)
1431 {
1432 if (*p == 'p')
1433 {
1434 np = *(p + 1);
1435
1436 if (!ISDIGIT (np))
1437 {
1438 /* Might be beginning of `p` extension. */
1439 if (std_ext_p)
1440 {
1441 *major_version = version;
1442 *minor_version = 0;
1443 return p;
1444 }
1445 else
1446 {
1447 rps->error_handler
1448 (_("%s: expect number after `%dp'"),
1449 arch, version);
1450 return NULL;
1451 }
1452 }
1453
1454 *major_version = version;
1455 major_p = false;
1456 version = 0;
1457 }
1458 else if (ISDIGIT (*p))
1459 version = (version * 10) + (*p - '0');
1460 else
1461 break;
1462 }
1463
1464 if (major_p)
1465 *major_version = version;
1466 else
1467 *minor_version = version;
1468
1469 /* We can not find any version in string. */
1470 if (*major_version == 0 && *minor_version == 0)
1471 {
1472 *major_version = RISCV_UNKNOWN_VERSION;
1473 *minor_version = RISCV_UNKNOWN_VERSION;
1474 }
1475
1476 return p;
1477 }
1478
1479 /* Return string which contain all supported standard extensions in
1480 canonical order. */
1481
1482 const char *
1483 riscv_supported_std_ext (void)
1484 {
1485 return "mafdqlcbjtpvn";
1486 }
1487
1488 /* Parsing function for standard extensions.
1489
1490 Return Value:
1491 Points to the end of extensions.
1492
1493 Arguments:
1494 `rps`: Hooks and status for parsing extensions.
1495 `arch`: Full ISA string.
1496 `p`: Curent parsing position. */
1497
1498 static const char *
1499 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1500 const char *arch,
1501 const char *p)
1502 {
1503 const char *all_std_exts = riscv_supported_std_ext ();
1504 const char *std_exts = all_std_exts;
1505 int major_version;
1506 int minor_version;
1507 char subset[2] = {0, 0};
1508
1509 /* First letter must start with i, e or g. */
1510 switch (*p)
1511 {
1512 case 'i':
1513 p = riscv_parsing_subset_version (rps, arch, ++p,
1514 &major_version,
1515 &minor_version, true);
1516 riscv_parse_add_subset (rps, "i",
1517 major_version,
1518 minor_version, false);
1519 break;
1520
1521 case 'e':
1522 p = riscv_parsing_subset_version (rps, arch, ++p,
1523 &major_version,
1524 &minor_version, true);
1525 riscv_parse_add_subset (rps, "e",
1526 major_version,
1527 minor_version, false);
1528 break;
1529
1530 case 'g':
1531 p = riscv_parsing_subset_version (rps, arch, ++p,
1532 &major_version,
1533 &minor_version, true);
1534 /* Expand g to imafd. */
1535 riscv_parse_add_subset (rps, "i",
1536 RISCV_UNKNOWN_VERSION,
1537 RISCV_UNKNOWN_VERSION, false);
1538 for ( ; *std_exts != 'q'; std_exts++)
1539 {
1540 subset[0] = *std_exts;
1541 riscv_parse_add_subset (rps, subset,
1542 RISCV_UNKNOWN_VERSION,
1543 RISCV_UNKNOWN_VERSION, false);
1544 }
1545 /* Add g as an implicit extension. */
1546 riscv_parse_add_subset (rps, "g",
1547 RISCV_UNKNOWN_VERSION,
1548 RISCV_UNKNOWN_VERSION, true);
1549 break;
1550
1551 default:
1552 rps->error_handler
1553 (_("%s: first ISA extension must be `e', `i' or `g'"),
1554 arch);
1555 return NULL;
1556 }
1557
1558 while (p != NULL && *p != '\0')
1559 {
1560 /* Stop when we parsed the known prefix class. */
1561 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1562 if (class != RV_ISA_CLASS_UNKNOWN)
1563 break;
1564
1565 if (*p == '_')
1566 {
1567 p++;
1568 continue;
1569 }
1570
1571 /* Checking canonical order. */
1572 char std_ext = *p;
1573 while (*std_exts && std_ext != *std_exts)
1574 std_exts++;
1575
1576 if (std_ext != *std_exts)
1577 {
1578 if (riscv_ext_order[(std_ext - 'a')] == 0)
1579 rps->error_handler
1580 (_("%s: unknown standard ISA extension `%c'"),
1581 arch, std_ext);
1582 else
1583 rps->error_handler
1584 (_("%s: standard ISA extension `%c' is not "
1585 "in canonical order"), arch, std_ext);
1586 return NULL;
1587 }
1588
1589 std_exts++;
1590 subset[0] = std_ext;
1591 p = riscv_parsing_subset_version (rps, arch, ++p,
1592 &major_version,
1593 &minor_version, true);
1594 riscv_parse_add_subset (rps, subset,
1595 major_version,
1596 minor_version, false);
1597 }
1598
1599 return p;
1600 }
1601
1602 /* Parsing function for prefixed extensions.
1603
1604 Return Value:
1605 Points to the end of extension.
1606
1607 Arguments:
1608 `rps`: Hooks and status for parsing extensions.
1609 `arch`: Full ISA string.
1610 `p`: Curent parsing position. */
1611
1612 static const char *
1613 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1614 const char *arch,
1615 const char *p)
1616 {
1617 int major_version;
1618 int minor_version;
1619 const char *last_name;
1620 enum riscv_prefix_ext_class class;
1621
1622 while (*p)
1623 {
1624 if (*p == '_')
1625 {
1626 p++;
1627 continue;
1628 }
1629
1630 class = riscv_get_prefix_class (p);
1631 if (class == RV_ISA_CLASS_UNKNOWN)
1632 {
1633 rps->error_handler
1634 (_("%s: unknown prefix class for the ISA extension `%s'"),
1635 arch, p);
1636 return NULL;
1637 }
1638
1639 char *subset = xstrdup (p);
1640 char *q = subset;
1641 const char *end_of_version;
1642
1643 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1644 ;
1645
1646 end_of_version =
1647 riscv_parsing_subset_version (rps, arch, q,
1648 &major_version,
1649 &minor_version, false);
1650 *q = '\0';
1651
1652 if (end_of_version == NULL)
1653 {
1654 free (subset);
1655 return NULL;
1656 }
1657
1658 /* Check if the prefix extension is known.
1659 For 'x', anything goes but it cannot simply be 'x'.
1660 For other prefixed extensions, it must be known from a list
1661 and cannot simply be the prefixed name. */
1662
1663 /* Check that the extension name is well-formed. */
1664 if (rps->check_unknown_prefixed_ext
1665 && !riscv_valid_prefixed_ext (subset))
1666 {
1667 rps->error_handler
1668 (_("%s: unknown prefixed ISA extension `%s'"),
1669 arch, subset);
1670 free (subset);
1671 return NULL;
1672 }
1673
1674 /* Check that the extension isn't duplicate. */
1675 last_name = rps->subset_list->tail->name;
1676 if (!strcasecmp (last_name, subset))
1677 {
1678 rps->error_handler
1679 (_("%s: duplicate prefixed ISA extension `%s'"),
1680 arch, subset);
1681 free (subset);
1682 return NULL;
1683 }
1684
1685 /* Check that the extension is in expected order. */
1686 if (riscv_compare_subsets (last_name, subset) > 0)
1687 {
1688 rps->error_handler
1689 (_("%s: prefixed ISA extension `%s' is not in expected "
1690 "order. It must come before `%s'"),
1691 arch, subset, last_name);
1692 free (subset);
1693 return NULL;
1694 }
1695
1696 riscv_parse_add_subset (rps, subset,
1697 major_version,
1698 minor_version, false);
1699 p += end_of_version - subset;
1700 free (subset);
1701
1702 if (*p != '\0' && *p != '_')
1703 {
1704 rps->error_handler
1705 (_("%s: prefixed ISA extension must separate with _"),
1706 arch);
1707 return NULL;
1708 }
1709 }
1710
1711 return p;
1712 }
1713
1714 /* Add the implicit extensions. */
1715
1716 static void
1717 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1718 {
1719 struct riscv_implicit_subset *t = riscv_implicit_subsets;
1720 for (; t->subset_name; t++)
1721 {
1722 riscv_subset_t *subset = NULL;
1723 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1724 && t->check_func (t->implicit_name, subset))
1725 riscv_parse_add_subset (rps, t->implicit_name,
1726 RISCV_UNKNOWN_VERSION,
1727 RISCV_UNKNOWN_VERSION, true);
1728 }
1729 }
1730
1731 /* Check extensions conflicts. */
1732
1733 static bool
1734 riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
1735 {
1736 riscv_subset_t *subset = NULL;
1737 int xlen = *rps->xlen;
1738 bool no_conflict = true;
1739
1740 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1741 && xlen > 32)
1742 {
1743 rps->error_handler
1744 (_("rv%d does not support the `e' extension"), xlen);
1745 no_conflict = false;
1746 }
1747 if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1748 && xlen < 64)
1749 {
1750 rps->error_handler
1751 (_("rv%d does not support the `q' extension"), xlen);
1752 no_conflict = false;
1753 }
1754 if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1755 && riscv_lookup_subset (rps->subset_list, "f", &subset))
1756 {
1757 rps->error_handler
1758 (_("rv32e does not support the `f' extension"));
1759 no_conflict = false;
1760 }
1761 return no_conflict;
1762 }
1763
1764 /* Function for parsing ISA string.
1765
1766 Return Value:
1767 Return TRUE on success.
1768
1769 Arguments:
1770 `rps`: Hooks and status for parsing extensions.
1771 `arch`: Full ISA string. */
1772
1773 bool
1774 riscv_parse_subset (riscv_parse_subset_t *rps,
1775 const char *arch)
1776 {
1777 const char *p;
1778
1779 for (p = arch; *p != '\0'; p++)
1780 {
1781 if (ISUPPER (*p))
1782 {
1783 rps->error_handler
1784 (_("%s: ISA string cannot contain uppercase letters"),
1785 arch);
1786 return false;
1787 }
1788 }
1789
1790 p = arch;
1791 if (startswith (p, "rv32"))
1792 {
1793 *rps->xlen = 32;
1794 p += 4;
1795 }
1796 else if (startswith (p, "rv64"))
1797 {
1798 *rps->xlen = 64;
1799 p += 4;
1800 }
1801 else
1802 {
1803 /* ISA string shouldn't be NULL or empty here. However,
1804 it might be empty only when we failed to merge the ISA
1805 string in the riscv_merge_attributes. We have already
1806 issued the correct error message in another side, so do
1807 not issue this error when the ISA string is empty. */
1808 if (strlen (arch))
1809 rps->error_handler (
1810 _("%s: ISA string must begin with rv32 or rv64"),
1811 arch);
1812 return false;
1813 }
1814
1815 /* Init the riscv_ext_order array to compare the order of extensions
1816 quickly. */
1817 riscv_init_ext_order ();
1818
1819 /* Parsing standard extension. */
1820 p = riscv_parse_std_ext (rps, arch, p);
1821
1822 if (p == NULL)
1823 return false;
1824
1825 /* Parse the different classes of extensions in the specified order. */
1826 while (*p != '\0')
1827 {
1828 p = riscv_parse_prefixed_ext (rps, arch, p);
1829
1830 if (p == NULL)
1831 return false;
1832 }
1833
1834 /* Finally add implicit extensions according to the current
1835 extensions. */
1836 riscv_parse_add_implicit_subsets (rps);
1837
1838 /* Check the conflicts. */
1839 return riscv_parse_check_conflicts (rps);
1840 }
1841
1842 /* Return the number of digits for the input. */
1843
1844 size_t
1845 riscv_estimate_digit (unsigned num)
1846 {
1847 size_t digit = 0;
1848 if (num == 0)
1849 return 1;
1850
1851 for (digit = 0; num ; num /= 10)
1852 digit++;
1853
1854 return digit;
1855 }
1856
1857 /* Auxiliary function to estimate string length of subset list. */
1858
1859 static size_t
1860 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1861 {
1862 if (subset == NULL)
1863 return 6; /* For rv32/rv64/rv128 and string terminator. */
1864
1865 return riscv_estimate_arch_strlen1 (subset->next)
1866 + strlen (subset->name)
1867 + riscv_estimate_digit (subset->major_version)
1868 + 1 /* For version seperator 'p'. */
1869 + riscv_estimate_digit (subset->minor_version)
1870 + 1 /* For underscore. */;
1871 }
1872
1873 /* Estimate the string length of this subset list. */
1874
1875 static size_t
1876 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1877 {
1878 return riscv_estimate_arch_strlen1 (subset_list->head);
1879 }
1880
1881 /* Auxiliary function to convert subset info to string. */
1882
1883 static void
1884 riscv_arch_str1 (riscv_subset_t *subset,
1885 char *attr_str, char *buf, size_t bufsz)
1886 {
1887 const char *underline = "_";
1888 riscv_subset_t *subset_t = subset;
1889
1890 if (subset_t == NULL)
1891 return;
1892
1893 /* No underline between rvXX and i/e. */
1894 if ((strcasecmp (subset_t->name, "i") == 0)
1895 || (strcasecmp (subset_t->name, "e") == 0))
1896 underline = "";
1897
1898 snprintf (buf, bufsz, "%s%s%dp%d",
1899 underline,
1900 subset_t->name,
1901 subset_t->major_version,
1902 subset_t->minor_version);
1903
1904 strncat (attr_str, buf, bufsz);
1905
1906 /* Skip 'i' extension after 'e', or skip extensions which
1907 versions are unknown. */
1908 while (subset_t->next
1909 && ((strcmp (subset_t->name, "e") == 0
1910 && strcmp (subset_t->next->name, "i") == 0)
1911 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
1912 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
1913 subset_t = subset_t->next;
1914
1915 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
1916 }
1917
1918 /* Convert subset information into string with explicit versions. */
1919
1920 char *
1921 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1922 {
1923 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1924 char *attr_str = xmalloc (arch_str_len);
1925 char *buf = xmalloc (arch_str_len);
1926
1927 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1928
1929 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1930 free (buf);
1931
1932 return attr_str;
1933 }