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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 4, /* 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 MINUS_ONE, /* 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 4, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 2, /* 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 2, /* 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 2, /* size */ 470 32, /* 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 TRUE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 2, /* 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 TRUE), /* pcrel_offset */ 647 648 /* 8-bit PC-relative branch offset. */ 649 HOWTO (R_RISCV_RVC_BRANCH, /* type */ 650 0, /* rightshift */ 651 2, /* size */ 652 32, /* 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 2, /* size */ 667 32, /* 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 2, /* size */ 682 32, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* 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 MINUS_ONE, /* dst_mask */ 856 FALSE), /* pcrel_offset */ 857 }; 858 859 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ 860 861 struct elf_reloc_map 862 { 863 bfd_reloc_code_real_type bfd_val; 864 enum elf_riscv_reloc_type elf_val; 865 }; 866 867 static const struct elf_reloc_map riscv_reloc_map[] = 868 { 869 { BFD_RELOC_NONE, R_RISCV_NONE }, 870 { BFD_RELOC_32, R_RISCV_32 }, 871 { BFD_RELOC_64, R_RISCV_64 }, 872 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 }, 873 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 }, 874 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 }, 875 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 }, 876 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 }, 877 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 }, 878 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 }, 879 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 }, 880 { BFD_RELOC_CTOR, R_RISCV_64 }, 881 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH }, 882 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 }, 883 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I }, 884 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S }, 885 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I }, 886 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S }, 887 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL }, 888 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT }, 889 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 }, 890 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL }, 891 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 }, 892 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 }, 893 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 }, 894 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 }, 895 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 }, 896 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 }, 897 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 }, 898 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 }, 899 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD }, 900 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S }, 901 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I }, 902 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 }, 903 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 }, 904 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN }, 905 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH }, 906 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP }, 907 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI }, 908 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I }, 909 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S }, 910 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I }, 911 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S }, 912 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX }, 913 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 }, 914 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 }, 915 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 }, 916 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 }, 917 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 }, 918 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL }, 919 }; 920 921 /* Given a BFD reloc type, return a howto structure. */ 922 923 reloc_howto_type * 924 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 925 bfd_reloc_code_real_type code) 926 { 927 unsigned int i; 928 929 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++) 930 if (riscv_reloc_map[i].bfd_val == code) 931 return &howto_table[(int) riscv_reloc_map[i].elf_val]; 932 933 bfd_set_error (bfd_error_bad_value); 934 return NULL; 935 } 936 937 reloc_howto_type * 938 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 939 { 940 unsigned int i; 941 942 for (i = 0; i < ARRAY_SIZE (howto_table); i++) 943 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0) 944 return &howto_table[i]; 945 946 return NULL; 947 } 948 949 reloc_howto_type * 950 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type) 951 { 952 if (r_type >= ARRAY_SIZE (howto_table)) 953 { 954 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"), 955 abfd, r_type); 956 bfd_set_error (bfd_error_bad_value); 957 return NULL; 958 } 959 return &howto_table[r_type]; 960 } 961 962 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */ 963 964 static bfd_reloc_status_type 965 riscv_elf_add_sub_reloc (bfd *abfd, 966 arelent *reloc_entry, 967 asymbol *symbol, 968 void *data, 969 asection *input_section, 970 bfd *output_bfd, 971 char **error_message ATTRIBUTE_UNUSED) 972 { 973 reloc_howto_type *howto = reloc_entry->howto; 974 bfd_vma relocation; 975 976 if (output_bfd != NULL 977 && (symbol->flags & BSF_SECTION_SYM) == 0 978 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) 979 { 980 reloc_entry->address += input_section->output_offset; 981 return bfd_reloc_ok; 982 } 983 984 if (output_bfd != NULL) 985 return bfd_reloc_continue; 986 987 relocation = symbol->value + symbol->section->output_section->vma 988 + symbol->section->output_offset + reloc_entry->addend; 989 bfd_vma old_value = bfd_get (howto->bitsize, abfd, 990 data + reloc_entry->address); 991 992 switch (howto->type) 993 { 994 case R_RISCV_ADD8: 995 case R_RISCV_ADD16: 996 case R_RISCV_ADD32: 997 case R_RISCV_ADD64: 998 relocation = old_value + relocation; 999 break; 1000 case R_RISCV_SUB6: 1001 case R_RISCV_SUB8: 1002 case R_RISCV_SUB16: 1003 case R_RISCV_SUB32: 1004 case R_RISCV_SUB64: 1005 relocation = old_value - relocation; 1006 break; 1007 } 1008 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address); 1009 1010 return bfd_reloc_ok; 1011 } 1012 1013 /* Parsing subset version. 1014 1015 Return Value: 1016 Points to the end of version 1017 1018 Arguments: 1019 `rps`: Hooks and status for parsing subset. 1020 `march`: Full arch string. 1021 `p`: Curent parsing position. 1022 `major_version`: Parsing result of major version, using 1023 default_major_version if version is not present in arch string. 1024 `minor_version`: Parsing result of minor version, set to 0 if version is 1025 not present in arch string, but set to `default_minor_version` if 1026 `major_version` using default_major_version. 1027 `std_ext_p`: True if parsing std extension. 1028 `use_default_version`: Set it to True if we need the default version. */ 1029 1030 static const char * 1031 riscv_parsing_subset_version (riscv_parse_subset_t *rps, 1032 const char *march, 1033 const char *p, 1034 unsigned *major_version, 1035 unsigned *minor_version, 1036 bfd_boolean std_ext_p, 1037 bfd_boolean *use_default_version) 1038 { 1039 bfd_boolean major_p = TRUE; 1040 unsigned version = 0; 1041 char np; 1042 1043 *major_version = 0; 1044 *minor_version = 0; 1045 for (; *p; ++p) 1046 { 1047 if (*p == 'p') 1048 { 1049 np = *(p + 1); 1050 1051 if (!ISDIGIT (np)) 1052 { 1053 /* Might be beginning of `p` extension. */ 1054 if (std_ext_p) 1055 { 1056 *major_version = version; 1057 *minor_version = 0; 1058 return p; 1059 } 1060 else 1061 { 1062 rps->error_handler 1063 (_("-march=%s: Expect number after `%dp'."), 1064 march, version); 1065 return NULL; 1066 } 1067 } 1068 1069 *major_version = version; 1070 major_p = FALSE; 1071 version = 0; 1072 } 1073 else if (ISDIGIT (*p)) 1074 version = (version * 10) + (*p - '0'); 1075 else 1076 break; 1077 } 1078 1079 if (major_p) 1080 *major_version = version; 1081 else 1082 *minor_version = version; 1083 1084 /* We can not find any version in string, need to parse default version. */ 1085 if (use_default_version != NULL 1086 && *major_version == 0 1087 && *minor_version == 0) 1088 *use_default_version = TRUE; 1089 return p; 1090 } 1091 1092 /* Return string which contain all supported standard extensions in 1093 canonical order. */ 1094 1095 const char * 1096 riscv_supported_std_ext (void) 1097 { 1098 return "mafdqlcbjtpvn"; 1099 } 1100 1101 /* Parsing function for standard extensions. 1102 1103 Return Value: 1104 Points to the end of extensions. 1105 1106 Arguments: 1107 `rps`: Hooks and status for parsing subset. 1108 `march`: Full arch string. 1109 `p`: Curent parsing position. */ 1110 1111 static const char * 1112 riscv_parse_std_ext (riscv_parse_subset_t *rps, 1113 const char *march, 1114 const char *p) 1115 { 1116 const char *all_std_exts = riscv_supported_std_ext (); 1117 const char *std_exts = all_std_exts; 1118 unsigned major_version = 0; 1119 unsigned minor_version = 0; 1120 char std_ext = '\0'; 1121 bfd_boolean use_default_version = FALSE; 1122 1123 /* First letter must start with i, e or g. */ 1124 switch (*p) 1125 { 1126 case 'i': 1127 p = riscv_parsing_subset_version (rps, 1128 march, 1129 ++p, 1130 &major_version, 1131 &minor_version, 1132 /* std_ext_p= */TRUE, 1133 &use_default_version); 1134 1135 /* Find the default version if needed. */ 1136 if (use_default_version 1137 && rps->get_default_version != NULL) 1138 rps->get_default_version ("i", 1139 &major_version, 1140 &minor_version); 1141 riscv_add_subset (rps->subset_list, "i", 1142 major_version, minor_version); 1143 break; 1144 1145 case 'e': 1146 p = riscv_parsing_subset_version (rps, 1147 march, 1148 ++p, 1149 &major_version, 1150 &minor_version, 1151 /* std_ext_p= */TRUE, 1152 &use_default_version); 1153 1154 /* Find the default version if needed. */ 1155 if (use_default_version 1156 && rps->get_default_version != NULL) 1157 rps->get_default_version ("e", 1158 &major_version, 1159 &minor_version); 1160 riscv_add_subset (rps->subset_list, "e", 1161 major_version, minor_version); 1162 1163 /* i-ext must be enabled. */ 1164 if (rps->get_default_version != NULL) 1165 rps->get_default_version ("i", 1166 &major_version, 1167 &minor_version); 1168 riscv_add_subset (rps->subset_list, "i", 1169 major_version, minor_version); 1170 1171 if (*rps->xlen > 32) 1172 { 1173 rps->error_handler 1174 (_("-march=%s: rv%de is not a valid base ISA"), 1175 march, *rps->xlen); 1176 return NULL; 1177 } 1178 break; 1179 1180 case 'g': 1181 /* The g-ext shouldn't has the version, so we just 1182 skip the setting if user set a version to it. */ 1183 p = riscv_parsing_subset_version (rps, 1184 march, 1185 ++p, 1186 &major_version, 1187 &minor_version, 1188 TRUE, 1189 &use_default_version); 1190 1191 /* i-ext must be enabled. */ 1192 if (rps->get_default_version != NULL) 1193 rps->get_default_version ("i", 1194 &major_version, 1195 &minor_version); 1196 riscv_add_subset (rps->subset_list, "i", 1197 major_version, minor_version); 1198 1199 for ( ; *std_exts != 'q'; std_exts++) 1200 { 1201 const char subset[] = {*std_exts, '\0'}; 1202 1203 if (rps->get_default_version != NULL) 1204 rps->get_default_version (subset, 1205 &major_version, 1206 &minor_version); 1207 riscv_add_subset (rps->subset_list, subset, 1208 major_version, minor_version); 1209 } 1210 break; 1211 1212 default: 1213 rps->error_handler 1214 (_("-march=%s: first ISA subset must be `e', `i' or `g'"), march); 1215 return NULL; 1216 } 1217 1218 /* The riscv_parsing_subset_version may set `p` to NULL, so I think we should 1219 skip parsing the string if `p` is NULL or value of `p` is `\0`. */ 1220 while (p != NULL && *p != '\0') 1221 { 1222 char subset[2] = {0, 0}; 1223 1224 if (*p == 'x' || *p == 's' || *p == 'z') 1225 break; 1226 1227 if (*p == '_') 1228 { 1229 p++; 1230 continue; 1231 } 1232 1233 std_ext = *p; 1234 1235 /* Checking canonical order. */ 1236 while (*std_exts && std_ext != *std_exts) std_exts++; 1237 1238 if (std_ext != *std_exts) 1239 { 1240 if (strchr (all_std_exts, std_ext) == NULL) 1241 rps->error_handler 1242 (_("-march=%s: unsupported ISA subset `%c'"), march, *p); 1243 else 1244 rps->error_handler 1245 (_("-march=%s: ISA string is not in canonical order. `%c'"), 1246 march, *p); 1247 return NULL; 1248 } 1249 1250 std_exts++; 1251 1252 use_default_version = FALSE; 1253 subset[0] = std_ext; 1254 p = riscv_parsing_subset_version (rps, 1255 march, 1256 ++p, 1257 &major_version, 1258 &minor_version, 1259 TRUE, 1260 &use_default_version); 1261 1262 /* Find the default version if needed. */ 1263 if (use_default_version 1264 && rps->get_default_version != NULL) 1265 rps->get_default_version (subset, 1266 &major_version, 1267 &minor_version); 1268 riscv_add_subset (rps->subset_list, subset, 1269 major_version, minor_version); 1270 } 1271 return p; 1272 } 1273 1274 /* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */ 1275 1276 riscv_isa_ext_class_t 1277 riscv_get_prefix_class (const char *arch) 1278 { 1279 switch (*arch) 1280 { 1281 case 's': return RV_ISA_CLASS_S; 1282 case 'x': return RV_ISA_CLASS_X; 1283 case 'z': return RV_ISA_CLASS_Z; 1284 default: return RV_ISA_CLASS_UNKNOWN; 1285 } 1286 } 1287 1288 /* Structure describing parameters to use when parsing a particular 1289 riscv_isa_ext_class_t. One of these should be provided for each 1290 possible class, except RV_ISA_CLASS_UNKNOWN. */ 1291 1292 typedef struct riscv_parse_config 1293 { 1294 /* Class of the extension. */ 1295 riscv_isa_ext_class_t class; 1296 1297 /* Lower-case prefix string for error printing 1298 and internal parser usage, e.g. "z", "x". */ 1299 const char *prefix; 1300 1301 /* Predicate which is used for checking whether 1302 this is a "known" extension. For 'x', 1303 it always returns true (since they are by 1304 definition non-standard and cannot be known. */ 1305 bfd_boolean (*ext_valid_p) (const char *); 1306 } riscv_parse_config_t; 1307 1308 /* Parse a generic prefixed extension. 1309 `rps`: Hooks and status for parsing subset. 1310 `march`: The full architecture string as passed in by "-march=...". 1311 `p`: Point from which to start parsing the -march string. 1312 `config`: What class of extensions to parse, predicate funcs, 1313 and strings to use in error reporting. */ 1314 1315 static const char * 1316 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps, 1317 const char *march, 1318 const char *p, 1319 const riscv_parse_config_t *config) 1320 { 1321 unsigned major_version = 0; 1322 unsigned minor_version = 0; 1323 const char *last_name; 1324 riscv_isa_ext_class_t class; 1325 bfd_boolean use_default_version; 1326 1327 while (*p) 1328 { 1329 if (*p == '_') 1330 { 1331 p++; 1332 continue; 1333 } 1334 1335 /* Assert that the current extension specifier matches our parsing 1336 class. */ 1337 class = riscv_get_prefix_class (p); 1338 if (class != config->class) 1339 break; 1340 1341 char *subset = xstrdup (p); 1342 char *q = subset; 1343 const char *end_of_version; 1344 1345 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q)) 1346 ; 1347 1348 use_default_version = FALSE; 1349 end_of_version = 1350 riscv_parsing_subset_version (rps, march, q, &major_version, 1351 &minor_version, FALSE, 1352 &use_default_version); 1353 *q = '\0'; 1354 1355 /* Check that the name is valid. 1356 For 'x', anything goes but it cannot simply be 'x'. 1357 For 's', it must be known from a list and cannot simply be 's'. 1358 For 'z', it must be known from a list and cannot simply be 'z'. */ 1359 1360 /* Check that the extension name is well-formed. */ 1361 if (!config->ext_valid_p (subset)) 1362 { 1363 rps->error_handler 1364 (_("-march=%s: Invalid or unknown %s ISA extension: '%s'"), 1365 march, config->prefix, subset); 1366 free (subset); 1367 return NULL; 1368 } 1369 1370 /* Check that the last item is not the same as this. */ 1371 last_name = rps->subset_list->tail->name; 1372 if (!strcasecmp (last_name, subset)) 1373 { 1374 rps->error_handler 1375 (_("-march=%s: Duplicate %s ISA extension: \'%s\'"), 1376 march, config->prefix, subset); 1377 free (subset); 1378 return NULL; 1379 } 1380 1381 /* Check that we are in alphabetical order within the subset. */ 1382 if (!strncasecmp (last_name, config->prefix, 1) 1383 && strcasecmp (last_name, subset) > 0) 1384 { 1385 rps->error_handler 1386 (_("\ 1387 -march=%s: %s ISA extension not in alphabetical order: \'%s\' must come before \'%s\'."), 1388 march, config->prefix, subset, last_name); 1389 free (subset); 1390 return NULL; 1391 } 1392 1393 /* Find the default version if needed. */ 1394 if (use_default_version 1395 && rps->get_default_version != NULL) 1396 rps->get_default_version (subset, 1397 &major_version, 1398 &minor_version); 1399 riscv_add_subset (rps->subset_list, subset, 1400 major_version, minor_version); 1401 1402 free (subset); 1403 p += end_of_version - subset; 1404 1405 if (*p != '\0' && *p != '_') 1406 { 1407 rps->error_handler (_("-march=%s: %s must separate with _"), 1408 march, config->prefix); 1409 return NULL; 1410 } 1411 } 1412 1413 return p; 1414 } 1415 1416 /* List of Z-class extensions that binutils should know about. 1417 Whether or not a particular entry is in this list will 1418 dictate if gas/ld will accept its presence in the -march 1419 string. 1420 1421 Example: To add an extension called "Zbb" (bitmanip base extension), 1422 add "zbb" string to the list (all lowercase). 1423 1424 Keep this list alphabetically ordered. */ 1425 1426 static const char * const riscv_std_z_ext_strtab[] = 1427 { 1428 "zicsr", NULL 1429 }; 1430 1431 /* Same as `riscv_std_z_ext_strtab', but for S-class extensions. */ 1432 1433 static const char * const riscv_std_s_ext_strtab[] = 1434 { 1435 NULL 1436 }; 1437 1438 /* For the extension EXT, search through the list of known extensions 1439 KNOWN_EXTS for a match, and return TRUE if found. */ 1440 1441 static bfd_boolean 1442 riscv_multi_letter_ext_valid_p (const char *ext, 1443 const char *const *known_exts) 1444 { 1445 size_t i; 1446 1447 for (i = 0; known_exts[i]; ++i) 1448 if (!strcmp (ext, known_exts[i])) 1449 return TRUE; 1450 1451 return FALSE; 1452 } 1453 1454 /* Predicator function for x-prefixed extensions. 1455 Anything goes, except the literal 'x'. */ 1456 1457 static bfd_boolean 1458 riscv_ext_x_valid_p (const char *arg) 1459 { 1460 if (!strcasecmp (arg, "x")) 1461 return FALSE; 1462 1463 return TRUE; 1464 } 1465 1466 /* Predicator functions for z-prefixed extensions. 1467 Only known z-extensions are permitted. */ 1468 1469 static bfd_boolean 1470 riscv_ext_z_valid_p (const char *arg) 1471 { 1472 return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab); 1473 } 1474 1475 /* Predicator function for 's' prefixed extensions. 1476 Must be either literal 's', or a known s-prefixed extension. */ 1477 1478 static bfd_boolean 1479 riscv_ext_s_valid_p (const char *arg) 1480 { 1481 return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab); 1482 } 1483 1484 /* Parsing order that is specified by the ISA manual. */ 1485 1486 static const riscv_parse_config_t parse_config[] = 1487 { 1488 {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p}, 1489 {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p}, 1490 {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p}, 1491 {RV_ISA_CLASS_UNKNOWN, NULL, NULL} 1492 }; 1493 1494 /* Function for parsing arch string. 1495 1496 Return Value: 1497 Return TRUE on success. 1498 1499 Arguments: 1500 `rps`: Hooks and status for parsing subset. 1501 `arch`: Arch string. */ 1502 1503 bfd_boolean 1504 riscv_parse_subset (riscv_parse_subset_t *rps, 1505 const char *arch) 1506 { 1507 const char *p = arch; 1508 size_t i; 1509 1510 if (strncmp (p, "rv32", 4) == 0) 1511 { 1512 *rps->xlen = 32; 1513 p += 4; 1514 } 1515 else if (strncmp (p, "rv64", 4) == 0) 1516 { 1517 *rps->xlen = 64; 1518 p += 4; 1519 } 1520 else 1521 { 1522 /* Arch string shouldn't be NULL or empty here. However, 1523 it might be empty only when we failed to merge the arch 1524 string in the riscv_merge_attributes. We have already 1525 issued the correct error message in another side, so do 1526 not issue this error when the arch string is empty. */ 1527 if (strlen (arch)) 1528 rps->error_handler ( 1529 _("-march=%s: ISA string must begin with rv32 or rv64"), 1530 arch); 1531 return FALSE; 1532 } 1533 1534 /* Parsing standard extension. */ 1535 p = riscv_parse_std_ext (rps, arch, p); 1536 1537 if (p == NULL) 1538 return FALSE; 1539 1540 /* Parse the different classes of extensions in the specified order. */ 1541 for (i = 0; i < ARRAY_SIZE (parse_config); ++i) { 1542 p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]); 1543 1544 if (p == NULL) 1545 return FALSE; 1546 } 1547 1548 if (*p != '\0') 1549 { 1550 rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"), 1551 arch, p); 1552 return FALSE; 1553 } 1554 1555 if (riscv_lookup_subset (rps->subset_list, "e") 1556 && riscv_lookup_subset (rps->subset_list, "f")) 1557 { 1558 rps->error_handler 1559 (_("-march=%s: rv32e does not support the `f' extension"), 1560 arch); 1561 return FALSE; 1562 } 1563 1564 if (riscv_lookup_subset (rps->subset_list, "d") 1565 && !riscv_lookup_subset (rps->subset_list, "f")) 1566 { 1567 rps->error_handler 1568 (_("-march=%s: `d' extension requires `f' extension"), 1569 arch); 1570 return FALSE; 1571 } 1572 1573 if (riscv_lookup_subset (rps->subset_list, "q") 1574 && !riscv_lookup_subset (rps->subset_list, "d")) 1575 { 1576 rps->error_handler 1577 (_("-march=%s: `q' extension requires `d' extension"), 1578 arch); 1579 return FALSE; 1580 } 1581 1582 if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64) 1583 { 1584 rps->error_handler 1585 (_("-march=%s: rv32 does not support the `q' extension"), 1586 arch); 1587 return FALSE; 1588 } 1589 return TRUE; 1590 } 1591 1592 /* Add new subset to list. */ 1593 1594 void 1595 riscv_add_subset (riscv_subset_list_t *subset_list, 1596 const char *subset, 1597 int major, 1598 int minor) 1599 { 1600 riscv_subset_t *s = xmalloc (sizeof *s); 1601 1602 if (subset_list->head == NULL) 1603 subset_list->head = s; 1604 1605 s->name = xstrdup (subset); 1606 s->major_version = major; 1607 s->minor_version = minor; 1608 s->next = NULL; 1609 1610 if (subset_list->tail != NULL) 1611 subset_list->tail->next = s; 1612 1613 subset_list->tail = s; 1614 } 1615 1616 /* Find subset in list without version checking, return NULL if not found. */ 1617 1618 riscv_subset_t * 1619 riscv_lookup_subset (const riscv_subset_list_t *subset_list, 1620 const char *subset) 1621 { 1622 return riscv_lookup_subset_version 1623 (subset_list, subset, 1624 RISCV_DONT_CARE_VERSION, 1625 RISCV_DONT_CARE_VERSION); 1626 } 1627 1628 /* Find subset in list with version checking, return NULL if not found. */ 1629 1630 riscv_subset_t * 1631 riscv_lookup_subset_version (const riscv_subset_list_t *subset_list, 1632 const char *subset, 1633 int major, int minor) 1634 { 1635 riscv_subset_t *s; 1636 1637 for (s = subset_list->head; s != NULL; s = s->next) 1638 if (strcasecmp (s->name, subset) == 0) 1639 { 1640 if ((major != RISCV_DONT_CARE_VERSION) 1641 && (s->major_version != major)) 1642 return NULL; 1643 1644 if ((minor != RISCV_DONT_CARE_VERSION) 1645 && (s->minor_version != minor)) 1646 return NULL; 1647 1648 return s; 1649 } 1650 1651 return NULL; 1652 } 1653 1654 /* Release subset list. */ 1655 1656 void 1657 riscv_release_subset_list (riscv_subset_list_t *subset_list) 1658 { 1659 while (subset_list->head != NULL) 1660 { 1661 riscv_subset_t *next = subset_list->head->next; 1662 free ((void *)subset_list->head->name); 1663 free (subset_list->head); 1664 subset_list->head = next; 1665 } 1666 1667 subset_list->tail = NULL; 1668 } 1669 1670 /* Return the number of digits for the input. */ 1671 1672 size_t 1673 riscv_estimate_digit (unsigned num) 1674 { 1675 size_t digit = 0; 1676 if (num == 0) 1677 return 1; 1678 1679 for (digit = 0; num ; num /= 10) 1680 digit++; 1681 1682 return digit; 1683 } 1684 1685 /* Auxiliary function to estimate string length of subset list. */ 1686 1687 static size_t 1688 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset) 1689 { 1690 if (subset == NULL) 1691 return 6; /* For rv32/rv64/rv128 and string terminator. */ 1692 1693 return riscv_estimate_arch_strlen1 (subset->next) 1694 + strlen (subset->name) 1695 + riscv_estimate_digit (subset->major_version) 1696 + 1 /* For version seperator: 'p'. */ 1697 + riscv_estimate_digit (subset->minor_version) 1698 + 1 /* For underscore. */; 1699 } 1700 1701 /* Estimate the string length of this subset list. */ 1702 1703 static size_t 1704 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list) 1705 { 1706 return riscv_estimate_arch_strlen1 (subset_list->head); 1707 } 1708 1709 /* Auxiliary function to convert subset info to string. */ 1710 1711 static void 1712 riscv_arch_str1 (riscv_subset_t *subset, 1713 char *attr_str, char *buf, size_t bufsz) 1714 { 1715 const char *underline = "_"; 1716 1717 if (subset == NULL) 1718 return; 1719 1720 /* No underline between rvXX and i/e. */ 1721 if ((strcasecmp (subset->name, "i") == 0) 1722 || (strcasecmp (subset->name, "e") == 0)) 1723 underline = ""; 1724 1725 snprintf (buf, bufsz, "%s%s%dp%d", 1726 underline, 1727 subset->name, 1728 subset->major_version, 1729 subset->minor_version); 1730 1731 strncat (attr_str, buf, bufsz); 1732 1733 /* Skip 'i' extension after 'e'. */ 1734 if ((strcasecmp (subset->name, "e") == 0) 1735 && subset->next 1736 && (strcasecmp (subset->next->name, "i") == 0)) 1737 riscv_arch_str1 (subset->next->next, attr_str, buf, bufsz); 1738 else 1739 riscv_arch_str1 (subset->next, attr_str, buf, bufsz); 1740 } 1741 1742 /* Convert subset info to string with explicit version info. */ 1743 1744 char * 1745 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset) 1746 { 1747 size_t arch_str_len = riscv_estimate_arch_strlen (subset); 1748 char *attr_str = xmalloc (arch_str_len); 1749 char *buf = xmalloc (arch_str_len); 1750 1751 snprintf (attr_str, arch_str_len, "rv%u", xlen); 1752 1753 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len); 1754 free (buf); 1755 1756 return attr_str; 1757 } 1758