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 *
riscv_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)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 *
riscv_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)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 *
riscv_elf_rtype_to_howto(bfd * abfd,unsigned int r_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
riscv_elf_add_sub_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)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   bfd_vma old_value = bfd_get (howto->bitsize, abfd,
1006 			       data + reloc_entry->address);
1007 
1008   switch (howto->type)
1009     {
1010     case R_RISCV_ADD8:
1011     case R_RISCV_ADD16:
1012     case R_RISCV_ADD32:
1013     case R_RISCV_ADD64:
1014       relocation = old_value + relocation;
1015       break;
1016     case R_RISCV_SUB6:
1017     case R_RISCV_SUB8:
1018     case R_RISCV_SUB16:
1019     case R_RISCV_SUB32:
1020     case R_RISCV_SUB64:
1021       relocation = old_value - relocation;
1022       break;
1023     }
1024   bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1025 
1026   return bfd_reloc_ok;
1027 }
1028 
1029 /* Always add the IMPLICIT for the SUBSET.  */
1030 
1031 static bool
check_implicit_always(const char * implicit ATTRIBUTE_UNUSED,riscv_subset_t * subset ATTRIBUTE_UNUSED)1032 check_implicit_always (const char *implicit ATTRIBUTE_UNUSED,
1033 		       riscv_subset_t *subset ATTRIBUTE_UNUSED)
1034 {
1035   return true;
1036 }
1037 
1038 /* Add the IMPLICIT only when the version of SUBSET less than 2.1.  */
1039 
1040 static bool
check_implicit_for_i(const char * implicit ATTRIBUTE_UNUSED,riscv_subset_t * subset)1041 check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED,
1042 		      riscv_subset_t *subset)
1043 {
1044   return (subset->major_version < 2
1045 	  || (subset->major_version == 2
1046 	      && subset->minor_version < 1));
1047 }
1048 
1049 /* Record all implicit information for the subsets.  */
1050 struct riscv_implicit_subset
1051 {
1052   const char *subset_name;
1053   const char *implicit_name;
1054   /* A function to determine if we need to add the implicit subset.  */
1055   bool (*check_func) (const char *, riscv_subset_t *);
1056 };
1057 static struct riscv_implicit_subset riscv_implicit_subsets[] =
1058 {
1059   {"e", "i",		check_implicit_always},
1060   {"i", "zicsr",	check_implicit_for_i},
1061   {"i", "zifencei",	check_implicit_for_i},
1062   {"g", "zicsr",	check_implicit_always},
1063   {"g", "zifencei",	check_implicit_always},
1064   {"q", "d",		check_implicit_always},
1065   {"d", "f",		check_implicit_always},
1066   {"f", "zicsr",	check_implicit_always},
1067   {NULL, NULL, NULL}
1068 };
1069 
1070 /* Lists of prefixed class extensions that binutils should know about.
1071    Whether or not a particular entry is in these lists will dictate if
1072    gas/ld will accept its presence in the architecture string.
1073 
1074    Please add the extensions to the lists in lower case.  However, keep
1075    these subsets in alphabetical order in these tables is recommended,
1076    although there is no impact on the current implementation.  */
1077 
1078 static const char * const riscv_std_z_ext_strtab[] =
1079 {
1080   "zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
1081 };
1082 
1083 static const char * const riscv_std_s_ext_strtab[] =
1084 {
1085   NULL
1086 };
1087 
1088 static const char * const riscv_std_h_ext_strtab[] =
1089 {
1090   NULL
1091 };
1092 
1093 static const char * const riscv_std_zxm_ext_strtab[] =
1094 {
1095   NULL
1096 };
1097 
1098 /* ISA extension prefixed name class.  Must define them in parsing order.  */
1099 enum riscv_prefix_ext_class
1100 {
1101   RV_ISA_CLASS_Z = 1,
1102   RV_ISA_CLASS_S,
1103   RV_ISA_CLASS_H,
1104   RV_ISA_CLASS_ZXM,
1105   RV_ISA_CLASS_X,
1106   RV_ISA_CLASS_UNKNOWN
1107 };
1108 
1109 /* Record the strings of the prefixed extensions, and their corresponding
1110    classes.  The more letters of the prefix string, the more forward it must
1111    be defined.  Otherwise, the riscv_get_prefix_class will map it to the
1112    wrong classes.  */
1113 struct riscv_parse_prefix_config
1114 {
1115   /* Class of the extension. */
1116   enum riscv_prefix_ext_class class;
1117 
1118   /* Prefix string for error printing and internal parser usage.  */
1119   const char *prefix;
1120 };
1121 static const struct riscv_parse_prefix_config parse_config[] =
1122 {
1123   {RV_ISA_CLASS_ZXM, "zxm"},
1124   {RV_ISA_CLASS_Z, "z"},
1125   {RV_ISA_CLASS_S, "s"},
1126   {RV_ISA_CLASS_H, "h"},
1127   {RV_ISA_CLASS_X, "x"},
1128   {RV_ISA_CLASS_UNKNOWN, NULL}
1129 };
1130 
1131 /* Get the prefixed name class for the extensions, the class also
1132    means the order of the prefixed extensions.  */
1133 
1134 static enum riscv_prefix_ext_class
riscv_get_prefix_class(const char * arch)1135 riscv_get_prefix_class (const char *arch)
1136 {
1137   int i = 0;
1138   while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
1139     {
1140       if (strncmp (arch, parse_config[i].prefix,
1141 		   strlen (parse_config[i].prefix)) == 0)
1142 	return parse_config[i].class;
1143       i++;
1144     }
1145   return RV_ISA_CLASS_UNKNOWN;
1146 }
1147 
1148 /* Check KNOWN_EXTS to see if the EXT is supported.  */
1149 
1150 static bool
riscv_known_prefixed_ext(const char * ext,const char * const * known_exts)1151 riscv_known_prefixed_ext (const char *ext,
1152 			  const char *const *known_exts)
1153 {
1154   size_t i;
1155   for (i = 0; known_exts[i]; ++i)
1156     if (strcmp (ext, known_exts[i]) == 0)
1157       return true;
1158   return false;
1159 }
1160 
1161 /* Check whether the prefixed extension is valid or not.  Return
1162    true if valid, otehrwise return false.  */
1163 
1164 static bool
riscv_valid_prefixed_ext(const char * ext)1165 riscv_valid_prefixed_ext (const char *ext)
1166 {
1167   enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
1168   switch (class)
1169   {
1170   case RV_ISA_CLASS_Z:
1171     return riscv_known_prefixed_ext (ext, riscv_std_z_ext_strtab);
1172   case RV_ISA_CLASS_ZXM:
1173     return riscv_known_prefixed_ext (ext, riscv_std_zxm_ext_strtab);
1174   case RV_ISA_CLASS_S:
1175     return riscv_known_prefixed_ext (ext, riscv_std_s_ext_strtab);
1176   case RV_ISA_CLASS_H:
1177     return riscv_known_prefixed_ext (ext, riscv_std_h_ext_strtab);
1178   case RV_ISA_CLASS_X:
1179     /* Only the single x is invalid.  */
1180     if (strcmp (ext, "x") != 0)
1181       return true;
1182   default:
1183     break;
1184   }
1185   return false;
1186 }
1187 
1188 /* Array is used to compare the orders of standard extensions quickly.  */
1189 static int riscv_ext_order[26] = {0};
1190 
1191 /* Init the riscv_ext_order array.  */
1192 
1193 static void
riscv_init_ext_order(void)1194 riscv_init_ext_order (void)
1195 {
1196   static bool inited = false;
1197   const char *std_base_exts = "eig";
1198   const char *std_remain_exts = riscv_supported_std_ext ();
1199   const char *ext;
1200   int order;
1201 
1202   if (inited)
1203     return;
1204 
1205   /* The orders of all standard extensions are positive.  */
1206   order = 1;
1207 
1208   /* Init the standard base extensions first.  */
1209   for (ext = std_base_exts; *ext; ext++)
1210     riscv_ext_order[(*ext - 'a')] = order++;
1211 
1212   /* Init the standard remaining extensions.  */
1213   for (ext = std_remain_exts; *ext; ext++)
1214     riscv_ext_order[(*ext - 'a')] = order++;
1215 
1216   /* Some of the prefixed keyword are not single letter, so we set
1217      their prefixed orders in the riscv_compare_subsets directly,
1218      not through the riscv_ext_order.  */
1219 
1220   inited = true;
1221 }
1222 
1223 /* Similar to the strcmp.  It returns an integer less than, equal to,
1224    or greater than zero if `subset2` is found, respectively, to be less
1225    than, to match, or be greater than `subset1`.
1226 
1227    The order values,
1228    Zero: Preserved keywords.
1229    Positive number: Standard extensions.
1230    Negative number: Prefixed keywords.  */
1231 
1232 int
riscv_compare_subsets(const char * subset1,const char * subset2)1233 riscv_compare_subsets (const char *subset1, const char *subset2)
1234 {
1235   int order1 = riscv_ext_order[(*subset1 - 'a')];
1236   int order2 = riscv_ext_order[(*subset2 - 'a')];
1237 
1238   /* Compare the standard extension first.  */
1239   if (order1 > 0 && order2 > 0)
1240     return order1 - order2;
1241 
1242   /* Set the prefixed orders to negative numbers.  */
1243   enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
1244   enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
1245 
1246   if (class1 != RV_ISA_CLASS_UNKNOWN)
1247     order1 = - (int) class1;
1248   if (class2 != RV_ISA_CLASS_UNKNOWN)
1249     order2 = - (int) class2;
1250 
1251   if (order1 == order2)
1252     {
1253       /* Compare the standard addition z extensions.  */
1254       if (class1 == RV_ISA_CLASS_Z)
1255 	{
1256 	  order1 = riscv_ext_order[(*++subset1 - 'a')];
1257 	  order2 = riscv_ext_order[(*++subset2 - 'a')];
1258 	  if (order1 != order2)
1259 	    return order1 - order2;
1260 	}
1261       return strcasecmp (++subset1, ++subset2);
1262     }
1263 
1264   return order2 - order1;
1265 }
1266 
1267 /* Find subset in the list.  Return TRUE and set `current` to the subset
1268    if it is found.  Otherwise, return FALSE and set `current` to the place
1269    where we should insert the subset.  However, return FALSE with the NULL
1270    `current` means we should insert the subset at the head of subset list,
1271    if needed.  */
1272 
1273 bool
riscv_lookup_subset(const riscv_subset_list_t * subset_list,const char * subset,riscv_subset_t ** current)1274 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1275 		     const char *subset,
1276 		     riscv_subset_t **current)
1277 {
1278   riscv_subset_t *s, *pre_s = NULL;
1279 
1280   for (s = subset_list->head;
1281        s != NULL;
1282        pre_s = s, s = s->next)
1283     {
1284       int cmp = riscv_compare_subsets (s->name, subset);
1285       if (cmp == 0)
1286 	{
1287 	  *current = s;
1288 	  return true;
1289 	}
1290       else if (cmp > 0)
1291 	break;
1292     }
1293   *current = pre_s;
1294   return false;
1295 }
1296 
1297 /* Add extension from ISA string to the last of the subset list.  */
1298 
1299 void
riscv_add_subset(riscv_subset_list_t * subset_list,const char * subset,int major,int minor)1300 riscv_add_subset (riscv_subset_list_t *subset_list,
1301 		  const char *subset,
1302 		  int major,
1303 		  int minor)
1304 {
1305   riscv_subset_t *s = xmalloc (sizeof *s);
1306 
1307   if (subset_list->head == NULL)
1308     subset_list->head = s;
1309 
1310   s->name = xstrdup (subset);
1311   s->major_version = major;
1312   s->minor_version = minor;
1313   s->next = NULL;
1314 
1315   if (subset_list->tail != NULL)
1316     subset_list->tail->next = s;
1317   subset_list->tail = s;
1318 }
1319 
1320 /* Add the implicit extension to the subset list.  Search the
1321    list first, and then find the right place to add.  */
1322 
1323 static void
riscv_add_implicit_subset(riscv_subset_list_t * subset_list,const char * subset,int major,int minor)1324 riscv_add_implicit_subset (riscv_subset_list_t *subset_list,
1325 			   const char *subset,
1326 			   int major,
1327 			   int minor)
1328 {
1329   riscv_subset_t *current, *new;
1330 
1331   if (riscv_lookup_subset (subset_list, subset, &current))
1332     return;
1333 
1334   new = xmalloc (sizeof *new);
1335   new->name = xstrdup (subset);
1336   new->major_version = major;
1337   new->minor_version = minor;
1338   new->next = NULL;
1339 
1340   if (current != NULL)
1341     {
1342       new->next = current->next;
1343       current->next = new;
1344     }
1345   else
1346     {
1347       new->next = subset_list->head;
1348       subset_list->head = new;
1349     }
1350 }
1351 
1352 /* We have to add all extensions from ISA string first, and then start to
1353    add their implicit extensions.  The extensions from ISA string must be
1354    set in order, so we can add them to the last of the subset list
1355    directly, without searching.
1356 
1357    Find the default versions for the extension before adding them to
1358    the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1359    Afterwards, report errors if we can not find their default versions.  */
1360 
1361 static void
riscv_parse_add_subset(riscv_parse_subset_t * rps,const char * subset,int major,int minor,bool implicit)1362 riscv_parse_add_subset (riscv_parse_subset_t *rps,
1363 			const char *subset,
1364 			int major,
1365 			int minor,
1366 			bool implicit)
1367 {
1368   int major_version = major;
1369   int minor_version = minor;
1370 
1371   if ((major_version == RISCV_UNKNOWN_VERSION
1372        || minor_version == RISCV_UNKNOWN_VERSION)
1373       && rps->get_default_version != NULL)
1374     rps->get_default_version (subset, &major_version, &minor_version);
1375 
1376   /* We don't care the versions of the implicit extensions.  */
1377   if (!implicit
1378       && (major_version == RISCV_UNKNOWN_VERSION
1379 	  || minor_version == RISCV_UNKNOWN_VERSION))
1380     {
1381       if (subset[0] == 'x')
1382 	rps->error_handler
1383 	  (_("x ISA extension `%s' must be set with the versions"),
1384 	   subset);
1385       else
1386 	rps->error_handler
1387 	  (_("cannot find default versions of the ISA extension `%s'"),
1388 	   subset);
1389       return;
1390     }
1391 
1392   if (!implicit)
1393     riscv_add_subset (rps->subset_list, subset,
1394 		      major_version, minor_version);
1395   else
1396     riscv_add_implicit_subset (rps->subset_list, subset,
1397 			       major_version, minor_version);
1398 }
1399 
1400 /* Release subset list.  */
1401 
1402 void
riscv_release_subset_list(riscv_subset_list_t * subset_list)1403 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1404 {
1405    while (subset_list->head != NULL)
1406     {
1407       riscv_subset_t *next = subset_list->head->next;
1408       free ((void *)subset_list->head->name);
1409       free (subset_list->head);
1410       subset_list->head = next;
1411     }
1412 
1413   subset_list->tail = NULL;
1414 }
1415 
1416 /* Parsing extension version.
1417 
1418    Return Value:
1419      Points to the end of version
1420 
1421    Arguments:
1422      `rps`: Hooks and status for parsing extensions.
1423      `march`: Full ISA string.
1424      `p`: Curent parsing position.
1425      `major_version`: Parsed major version.
1426      `minor_version`: Parsed minor version.
1427      `std_ext_p`: True if parsing standard extension.  */
1428 
1429 static const char *
riscv_parsing_subset_version(riscv_parse_subset_t * rps,const char * march,const char * p,int * major_version,int * minor_version,bool std_ext_p)1430 riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1431 			      const char *march,
1432 			      const char *p,
1433 			      int *major_version,
1434 			      int *minor_version,
1435 			      bool std_ext_p)
1436 {
1437   bool major_p = true;
1438   int version = 0;
1439   char np;
1440 
1441   *major_version = 0;
1442   *minor_version = 0;
1443   for (; *p; ++p)
1444     {
1445       if (*p == 'p')
1446 	{
1447 	  np = *(p + 1);
1448 
1449 	  if (!ISDIGIT (np))
1450 	    {
1451 	      /* Might be beginning of `p` extension.  */
1452 	      if (std_ext_p)
1453 		{
1454 		  *major_version = version;
1455 		  *minor_version = 0;
1456 		  return p;
1457 		}
1458 	      else
1459 		{
1460 		  rps->error_handler
1461 		    (_("-march=%s: expect number after `%dp'"),
1462 		     march, version);
1463 		  return NULL;
1464 		}
1465 	    }
1466 
1467 	  *major_version = version;
1468 	  major_p = false;
1469 	  version = 0;
1470 	}
1471       else if (ISDIGIT (*p))
1472 	version = (version * 10) + (*p - '0');
1473       else
1474 	break;
1475     }
1476 
1477   if (major_p)
1478     *major_version = version;
1479   else
1480     *minor_version = version;
1481 
1482   /* We can not find any version in string.  */
1483   if (*major_version == 0 && *minor_version == 0)
1484     {
1485       *major_version = RISCV_UNKNOWN_VERSION;
1486       *minor_version = RISCV_UNKNOWN_VERSION;
1487     }
1488 
1489   return p;
1490 }
1491 
1492 /* Return string which contain all supported standard extensions in
1493    canonical order.  */
1494 
1495 const char *
riscv_supported_std_ext(void)1496 riscv_supported_std_ext (void)
1497 {
1498   return "mafdqlcbjtpvn";
1499 }
1500 
1501 /* Parsing function for standard extensions.
1502 
1503    Return Value:
1504      Points to the end of extensions.
1505 
1506    Arguments:
1507      `rps`: Hooks and status for parsing extensions.
1508      `march`: Full ISA string.
1509      `p`: Curent parsing position.  */
1510 
1511 static const char *
riscv_parse_std_ext(riscv_parse_subset_t * rps,const char * march,const char * p)1512 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1513 		     const char *march,
1514 		     const char *p)
1515 {
1516   const char *all_std_exts = riscv_supported_std_ext ();
1517   const char *std_exts = all_std_exts;
1518   int major_version;
1519   int minor_version;
1520   char subset[2] = {0, 0};
1521 
1522   /* First letter must start with i, e or g.  */
1523   switch (*p)
1524     {
1525       case 'i':
1526 	p = riscv_parsing_subset_version (rps, march, ++p,
1527 					  &major_version,
1528 					  &minor_version, true);
1529 	riscv_parse_add_subset (rps, "i",
1530 				major_version,
1531 				minor_version, false);
1532 	break;
1533 
1534       case 'e':
1535 	p = riscv_parsing_subset_version (rps, march, ++p,
1536 					  &major_version,
1537 					  &minor_version, true);
1538 	riscv_parse_add_subset (rps, "e",
1539 				major_version,
1540 				minor_version, false);
1541 	if (*rps->xlen > 32)
1542 	  {
1543 	    rps->error_handler
1544 	      (_("-march=%s: rv%de is not a valid base ISA"),
1545 	       march, *rps->xlen);
1546 	    return NULL;
1547 	  }
1548 	break;
1549 
1550       case 'g':
1551 	p = riscv_parsing_subset_version (rps, march, ++p,
1552 					  &major_version,
1553 					  &minor_version, true);
1554 	/* Expand g to imafd.  */
1555 	riscv_parse_add_subset (rps, "i",
1556 				RISCV_UNKNOWN_VERSION,
1557 				RISCV_UNKNOWN_VERSION, false);
1558 	for ( ; *std_exts != 'q'; std_exts++)
1559 	  {
1560 	    subset[0] = *std_exts;
1561 	    riscv_parse_add_subset (rps, subset,
1562 				    RISCV_UNKNOWN_VERSION,
1563 				    RISCV_UNKNOWN_VERSION, false);
1564 	  }
1565 	/* Add g as an implicit extension.  */
1566 	riscv_parse_add_subset (rps, "g",
1567 				RISCV_UNKNOWN_VERSION,
1568 				RISCV_UNKNOWN_VERSION, true);
1569 	break;
1570 
1571       default:
1572 	rps->error_handler
1573 	  (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1574 	   march);
1575 	return NULL;
1576     }
1577 
1578   while (p != NULL && *p != '\0')
1579     {
1580       /* Stop when we parsed the known prefix class.  */
1581       enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
1582       if (class != RV_ISA_CLASS_UNKNOWN)
1583 	break;
1584 
1585       if (*p == '_')
1586 	{
1587 	  p++;
1588 	  continue;
1589 	}
1590 
1591       /* Checking canonical order.  */
1592       char std_ext = *p;
1593       while (*std_exts && std_ext != *std_exts)
1594 	std_exts++;
1595 
1596       if (std_ext != *std_exts)
1597 	{
1598 	  if (riscv_ext_order[(std_ext - 'a')] == 0)
1599 	    rps->error_handler
1600 	      (_("-march=%s: unknown standard and prefixed ISA "
1601 		 "extension `%s'"), march, p);
1602 	  else
1603 	    rps->error_handler
1604 	      (_("-march=%s: standard ISA extension `%c' is not "
1605 		 "in canonical order"), march, std_ext);
1606 	  return NULL;
1607 	}
1608 
1609       std_exts++;
1610       subset[0] = std_ext;
1611       p = riscv_parsing_subset_version (rps, march, ++p,
1612 					&major_version,
1613 					&minor_version, true);
1614       riscv_parse_add_subset (rps, subset,
1615 			      major_version,
1616 			      minor_version, false);
1617     }
1618 
1619   return p;
1620 }
1621 
1622 /* Parsing function for prefixed extensions.
1623 
1624    Return Value:
1625      Points to the end of extension.
1626 
1627    Arguments:
1628      `rps`: Hooks and status for parsing extensions.
1629      `march`: Full ISA string.
1630      `p`: Curent parsing position.  */
1631 
1632 static const char *
riscv_parse_prefixed_ext(riscv_parse_subset_t * rps,const char * march,const char * p)1633 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1634 			  const char *march,
1635 			  const char *p)
1636 {
1637   int major_version;
1638   int minor_version;
1639   const char *last_name;
1640   enum riscv_prefix_ext_class class;
1641 
1642   while (*p)
1643     {
1644       if (*p == '_')
1645 	{
1646 	  p++;
1647 	  continue;
1648 	}
1649 
1650       class = riscv_get_prefix_class (p);
1651       if (class == RV_ISA_CLASS_UNKNOWN)
1652 	{
1653 	  rps->error_handler
1654 	    (_("-march=%s: unknown prefix class for the ISA extension `%s'"),
1655 	     march, p);
1656 	  return NULL;
1657 	}
1658 
1659       char *subset = xstrdup (p);
1660       char *q = subset;
1661       const char *end_of_version;
1662 
1663       while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1664 	;
1665 
1666       end_of_version =
1667 	riscv_parsing_subset_version (rps, march, q,
1668 				      &major_version,
1669 				      &minor_version, false);
1670       *q = '\0';
1671 
1672       if (end_of_version == NULL)
1673 	{
1674 	  free (subset);
1675 	  return NULL;
1676 	}
1677 
1678       /* Check if the prefix extension is known.
1679 	 For 'x', anything goes but it cannot simply be 'x'.
1680 	 For other prefixed extensions, it must be known from a list
1681 	 and cannot simply be the prefixed name.  */
1682 
1683       /* Check that the extension name is well-formed.  */
1684       if (rps->check_unknown_prefixed_ext
1685 	  && !riscv_valid_prefixed_ext (subset))
1686 	{
1687 	  rps->error_handler
1688 	    (_("-march=%s: unknown prefixed ISA extension `%s'"),
1689 	     march, subset);
1690 	  free (subset);
1691 	  return NULL;
1692 	}
1693 
1694       /* Check that the extension isn't duplicate.  */
1695       last_name = rps->subset_list->tail->name;
1696       if (!strcasecmp (last_name, subset))
1697 	{
1698 	  rps->error_handler
1699 	    (_("-march=%s: duplicate prefixed ISA extension `%s'"),
1700 	     march, subset);
1701 	  free (subset);
1702 	  return NULL;
1703 	}
1704 
1705       /* Check that the extension is in expected order.  */
1706       if (riscv_compare_subsets (last_name, subset) > 0)
1707 	{
1708 	  rps->error_handler
1709 	    (_("-march=%s: prefixed ISA extension `%s' is not in expected "
1710 	       "order.  It must come before `%s'"),
1711 	     march, subset, last_name);
1712 	  free (subset);
1713 	  return NULL;
1714 	}
1715 
1716       riscv_parse_add_subset (rps, subset,
1717 			      major_version,
1718 			      minor_version, false);
1719       p += end_of_version - subset;
1720       free (subset);
1721 
1722       if (*p != '\0' && *p != '_')
1723 	{
1724 	  rps->error_handler
1725 	    (_("-march=%s: prefixed ISA extension must separate with _"),
1726 	     march);
1727 	  return NULL;
1728 	}
1729     }
1730 
1731   return p;
1732 }
1733 
1734 /* Add the implicit extensions.  */
1735 
1736 static void
riscv_parse_add_implicit_subsets(riscv_parse_subset_t * rps)1737 riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
1738 {
1739   struct riscv_implicit_subset *t = riscv_implicit_subsets;
1740   for (; t->subset_name; t++)
1741     {
1742       riscv_subset_t *subset = NULL;
1743       if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
1744 	  && t->check_func (t->implicit_name, subset))
1745 	riscv_parse_add_subset (rps, t->implicit_name,
1746 				RISCV_UNKNOWN_VERSION,
1747 				RISCV_UNKNOWN_VERSION, true);
1748     }
1749 }
1750 
1751 /* Function for parsing ISA string.
1752 
1753    Return Value:
1754      Return TRUE on success.
1755 
1756    Arguments:
1757      `rps`: Hooks and status for parsing extensions.
1758      `arch`: Full ISA string.  */
1759 
1760 bool
riscv_parse_subset(riscv_parse_subset_t * rps,const char * arch)1761 riscv_parse_subset (riscv_parse_subset_t *rps,
1762 		    const char *arch)
1763 {
1764   riscv_subset_t *subset = NULL;
1765   const char *p;
1766   bool no_conflict = true;
1767 
1768   for (p = arch; *p != '\0'; p++)
1769     {
1770       if (ISUPPER (*p))
1771 	{
1772 	  rps->error_handler
1773 	    (_("-march=%s: ISA string cannot contain uppercase letters"),
1774 	     arch);
1775 	  return false;
1776 	}
1777     }
1778 
1779   p = arch;
1780   if (startswith (p, "rv32"))
1781     {
1782       *rps->xlen = 32;
1783       p += 4;
1784     }
1785   else if (startswith (p, "rv64"))
1786     {
1787       *rps->xlen = 64;
1788       p += 4;
1789     }
1790   else
1791     {
1792       /* ISA string shouldn't be NULL or empty here.  However,
1793 	 it might be empty only when we failed to merge the ISA
1794 	 string in the riscv_merge_attributes.  We have already
1795 	 issued the correct error message in another side, so do
1796 	 not issue this error when the ISA string is empty.  */
1797       if (strlen (arch))
1798 	rps->error_handler (
1799 	  _("-march=%s: ISA string must begin with rv32 or rv64"),
1800 	  arch);
1801       return false;
1802     }
1803 
1804   /* Init the riscv_ext_order array to compare the order of extensions
1805      quickly.  */
1806   riscv_init_ext_order ();
1807 
1808   /* Parsing standard extension.  */
1809   p = riscv_parse_std_ext (rps, arch, p);
1810 
1811   if (p == NULL)
1812     return false;
1813 
1814   /* Parse the different classes of extensions in the specified order.  */
1815   while (*p != '\0')
1816     {
1817       p = riscv_parse_prefixed_ext (rps, arch, p);
1818 
1819       if (p == NULL)
1820         return false;
1821     }
1822 
1823   /* Finally add implicit extensions according to the current
1824      extensions.  */
1825   riscv_parse_add_implicit_subsets (rps);
1826 
1827   /* Check the conflicts.  */
1828   if (riscv_lookup_subset (rps->subset_list, "e", &subset)
1829       && riscv_lookup_subset (rps->subset_list, "f", &subset))
1830     {
1831       rps->error_handler
1832 	(_("-march=%s: rv32e does not support the `f' extension"),
1833 	 arch);
1834       no_conflict = false;
1835     }
1836   if (riscv_lookup_subset (rps->subset_list, "q", &subset)
1837       && *rps->xlen < 64)
1838     {
1839       rps->error_handler
1840 	(_("-march=%s: rv32 does not support the `q' extension"),
1841 	 arch);
1842       no_conflict = false;
1843     }
1844   return no_conflict;
1845 }
1846 
1847 /* Return the number of digits for the input.  */
1848 
1849 size_t
riscv_estimate_digit(unsigned num)1850 riscv_estimate_digit (unsigned num)
1851 {
1852   size_t digit = 0;
1853   if (num == 0)
1854     return 1;
1855 
1856   for (digit = 0; num ; num /= 10)
1857     digit++;
1858 
1859   return digit;
1860 }
1861 
1862 /* Auxiliary function to estimate string length of subset list.  */
1863 
1864 static size_t
riscv_estimate_arch_strlen1(const riscv_subset_t * subset)1865 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1866 {
1867   if (subset == NULL)
1868     return 6; /* For rv32/rv64/rv128 and string terminator.  */
1869 
1870   return riscv_estimate_arch_strlen1 (subset->next)
1871 	 + strlen (subset->name)
1872 	 + riscv_estimate_digit (subset->major_version)
1873 	 + 1 /* For version seperator 'p'.  */
1874 	 + riscv_estimate_digit (subset->minor_version)
1875 	 + 1 /* For underscore.  */;
1876 }
1877 
1878 /* Estimate the string length of this subset list.  */
1879 
1880 static size_t
riscv_estimate_arch_strlen(const riscv_subset_list_t * subset_list)1881 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1882 {
1883   return riscv_estimate_arch_strlen1 (subset_list->head);
1884 }
1885 
1886 /* Auxiliary function to convert subset info to string.  */
1887 
1888 static void
riscv_arch_str1(riscv_subset_t * subset,char * attr_str,char * buf,size_t bufsz)1889 riscv_arch_str1 (riscv_subset_t *subset,
1890 		 char *attr_str, char *buf, size_t bufsz)
1891 {
1892   const char *underline = "_";
1893   riscv_subset_t *subset_t = subset;
1894 
1895   if (subset_t == NULL)
1896     return;
1897 
1898   /* No underline between rvXX and i/e.  */
1899   if ((strcasecmp (subset_t->name, "i") == 0)
1900       || (strcasecmp (subset_t->name, "e") == 0))
1901     underline = "";
1902 
1903   snprintf (buf, bufsz, "%s%s%dp%d",
1904 	    underline,
1905 	    subset_t->name,
1906 	    subset_t->major_version,
1907 	    subset_t->minor_version);
1908 
1909   strncat (attr_str, buf, bufsz);
1910 
1911   /* Skip 'i' extension after 'e', or skip extensions which
1912      versions are unknown.  */
1913   while (subset_t->next
1914 	 && ((strcmp (subset_t->name, "e") == 0
1915 	      && strcmp (subset_t->next->name, "i") == 0)
1916 	     || subset_t->next->major_version == RISCV_UNKNOWN_VERSION
1917 	     || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION))
1918     subset_t = subset_t->next;
1919 
1920   riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz);
1921 }
1922 
1923 /* Convert subset information into string with explicit versions.  */
1924 
1925 char *
riscv_arch_str(unsigned xlen,const riscv_subset_list_t * subset)1926 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1927 {
1928   size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1929   char *attr_str = xmalloc (arch_str_len);
1930   char *buf = xmalloc (arch_str_len);
1931 
1932   snprintf (attr_str, arch_str_len, "rv%u", xlen);
1933 
1934   riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1935   free (buf);
1936 
1937   return attr_str;
1938 }
1939