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