1 /* RISC-V-specific support for ELF. 2 Copyright 2011-2014 Free Software Foundation, Inc. 3 4 Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley. 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; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 22 MA 02110-1301, USA. */ 23 24 #include "sysdep.h" 25 #include "bfd.h" 26 #include "libbfd.h" 27 #include "elf-bfd.h" 28 #include "elf/riscv.h" 29 #include "opcode/riscv.h" 30 #include "libiberty.h" 31 #include "elfxx-riscv.h" 32 #include <stdint.h> 33 34 #define MINUS_ONE ((bfd_vma)0 - 1) 35 36 /* The relocation table used for SHT_RELA sections. */ 37 38 static reloc_howto_type howto_table[] = 39 { 40 /* No relocation. */ 41 HOWTO (R_RISCV_NONE, /* type */ 42 0, /* rightshift */ 43 0, /* size (0 = byte, 1 = short, 2 = long) */ 44 0, /* bitsize */ 45 FALSE, /* pc_relative */ 46 0, /* bitpos */ 47 complain_overflow_dont, /* complain_on_overflow */ 48 bfd_elf_generic_reloc, /* special_function */ 49 "R_RISCV_NONE", /* name */ 50 FALSE, /* partial_inplace */ 51 0, /* src_mask */ 52 0, /* dst_mask */ 53 FALSE), /* pcrel_offset */ 54 55 /* 32 bit relocation. */ 56 HOWTO (R_RISCV_32, /* type */ 57 0, /* rightshift */ 58 2, /* size (0 = byte, 1 = short, 2 = long) */ 59 32, /* bitsize */ 60 FALSE, /* pc_relative */ 61 0, /* bitpos */ 62 complain_overflow_dont, /* complain_on_overflow */ 63 bfd_elf_generic_reloc, /* special_function */ 64 "R_RISCV_32", /* name */ 65 FALSE, /* partial_inplace */ 66 0, /* src_mask */ 67 0xffffffff, /* dst_mask */ 68 FALSE), /* pcrel_offset */ 69 70 /* 64 bit relocation. */ 71 HOWTO (R_RISCV_64, /* type */ 72 0, /* rightshift */ 73 4, /* size (0 = byte, 1 = short, 2 = long) */ 74 64, /* bitsize */ 75 FALSE, /* pc_relative */ 76 0, /* bitpos */ 77 complain_overflow_dont, /* complain_on_overflow */ 78 bfd_elf_generic_reloc, /* special_function */ 79 "R_RISCV_64", /* name */ 80 FALSE, /* partial_inplace */ 81 0, /* src_mask */ 82 MINUS_ONE, /* dst_mask */ 83 FALSE), /* pcrel_offset */ 84 85 /* Relocation against a local symbol in a shared object. */ 86 HOWTO (R_RISCV_RELATIVE, /* type */ 87 0, /* rightshift */ 88 2, /* size (0 = byte, 1 = short, 2 = long) */ 89 32, /* bitsize */ 90 FALSE, /* pc_relative */ 91 0, /* bitpos */ 92 complain_overflow_dont, /* complain_on_overflow */ 93 bfd_elf_generic_reloc, /* special_function */ 94 "R_RISCV_RELATIVE", /* name */ 95 FALSE, /* partial_inplace */ 96 0, /* src_mask */ 97 0xffffffff, /* dst_mask */ 98 FALSE), /* pcrel_offset */ 99 100 HOWTO (R_RISCV_COPY, /* type */ 101 0, /* rightshift */ 102 0, /* this one is variable size */ 103 0, /* bitsize */ 104 FALSE, /* pc_relative */ 105 0, /* bitpos */ 106 complain_overflow_bitfield, /* complain_on_overflow */ 107 bfd_elf_generic_reloc, /* special_function */ 108 "R_RISCV_COPY", /* name */ 109 FALSE, /* partial_inplace */ 110 0x0, /* src_mask */ 111 0x0, /* dst_mask */ 112 FALSE), /* pcrel_offset */ 113 114 HOWTO (R_RISCV_JUMP_SLOT, /* type */ 115 0, /* rightshift */ 116 4, /* size (0 = byte, 1 = short, 2 = long) */ 117 64, /* bitsize */ 118 FALSE, /* pc_relative */ 119 0, /* bitpos */ 120 complain_overflow_bitfield, /* complain_on_overflow */ 121 bfd_elf_generic_reloc, /* special_function */ 122 "R_RISCV_JUMP_SLOT", /* name */ 123 FALSE, /* partial_inplace */ 124 0x0, /* src_mask */ 125 0x0, /* dst_mask */ 126 FALSE), /* pcrel_offset */ 127 128 /* Dynamic TLS relocations. */ 129 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */ 130 0, /* rightshift */ 131 4, /* size (0 = byte, 1 = short, 2 = long) */ 132 32, /* bitsize */ 133 FALSE, /* pc_relative */ 134 0, /* bitpos */ 135 complain_overflow_dont, /* complain_on_overflow */ 136 bfd_elf_generic_reloc, /* special_function */ 137 "R_RISCV_TLS_DTPMOD32", /* name */ 138 FALSE, /* partial_inplace */ 139 MINUS_ONE, /* src_mask */ 140 MINUS_ONE, /* dst_mask */ 141 FALSE), /* pcrel_offset */ 142 143 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */ 144 0, /* rightshift */ 145 4, /* size (0 = byte, 1 = short, 2 = long) */ 146 64, /* bitsize */ 147 FALSE, /* pc_relative */ 148 0, /* bitpos */ 149 complain_overflow_dont, /* complain_on_overflow */ 150 bfd_elf_generic_reloc, /* special_function */ 151 "R_RISCV_TLS_DTPMOD64", /* name */ 152 FALSE, /* partial_inplace */ 153 MINUS_ONE, /* src_mask */ 154 MINUS_ONE, /* dst_mask */ 155 FALSE), /* pcrel_offset */ 156 157 HOWTO (R_RISCV_TLS_DTPREL32, /* type */ 158 0, /* rightshift */ 159 4, /* size (0 = byte, 1 = short, 2 = long) */ 160 32, /* bitsize */ 161 FALSE, /* pc_relative */ 162 0, /* bitpos */ 163 complain_overflow_dont, /* complain_on_overflow */ 164 bfd_elf_generic_reloc, /* special_function */ 165 "R_RISCV_TLS_DTPREL32", /* name */ 166 TRUE, /* partial_inplace */ 167 MINUS_ONE, /* src_mask */ 168 MINUS_ONE, /* dst_mask */ 169 FALSE), /* pcrel_offset */ 170 171 HOWTO (R_RISCV_TLS_DTPREL64, /* type */ 172 0, /* rightshift */ 173 4, /* size (0 = byte, 1 = short, 2 = long) */ 174 64, /* bitsize */ 175 FALSE, /* pc_relative */ 176 0, /* bitpos */ 177 complain_overflow_dont, /* complain_on_overflow */ 178 bfd_elf_generic_reloc, /* special_function */ 179 "R_RISCV_TLS_DTPREL64", /* name */ 180 TRUE, /* partial_inplace */ 181 MINUS_ONE, /* src_mask */ 182 MINUS_ONE, /* dst_mask */ 183 FALSE), /* pcrel_offset */ 184 185 HOWTO (R_RISCV_TLS_TPREL32, /* type */ 186 0, /* rightshift */ 187 2, /* size (0 = byte, 1 = short, 2 = long) */ 188 32, /* bitsize */ 189 FALSE, /* pc_relative */ 190 0, /* bitpos */ 191 complain_overflow_dont, /* complain_on_overflow */ 192 bfd_elf_generic_reloc, /* special_function */ 193 "R_RISCV_TLS_TPREL32", /* name */ 194 FALSE, /* partial_inplace */ 195 MINUS_ONE, /* src_mask */ 196 MINUS_ONE, /* dst_mask */ 197 FALSE), /* pcrel_offset */ 198 199 HOWTO (R_RISCV_TLS_TPREL64, /* type */ 200 0, /* rightshift */ 201 4, /* size (0 = byte, 1 = short, 2 = long) */ 202 64, /* bitsize */ 203 FALSE, /* pc_relative */ 204 0, /* bitpos */ 205 complain_overflow_dont, /* complain_on_overflow */ 206 bfd_elf_generic_reloc, /* special_function */ 207 "R_RISCV_TLS_TPREL64", /* name */ 208 FALSE, /* partial_inplace */ 209 MINUS_ONE, /* src_mask */ 210 MINUS_ONE, /* dst_mask */ 211 FALSE), /* pcrel_offset */ 212 213 EMPTY_HOWTO (12), 214 EMPTY_HOWTO (13), 215 EMPTY_HOWTO (14), 216 EMPTY_HOWTO (15), 217 218 /* 12-bit PC-relative branch offset. */ 219 HOWTO (R_RISCV_BRANCH, /* type */ 220 0, /* rightshift */ 221 2, /* size (0 = byte, 1 = short, 2 = long) */ 222 32, /* bitsize */ 223 TRUE, /* pc_relative */ 224 0, /* bitpos */ 225 complain_overflow_signed, /* complain_on_overflow */ 226 bfd_elf_generic_reloc, /* special_function */ 227 "R_RISCV_BRANCH", /* name */ 228 FALSE, /* partial_inplace */ 229 0, /* src_mask */ 230 ENCODE_SBTYPE_IMM(-1U),/* dst_mask */ 231 TRUE), /* pcrel_offset */ 232 233 /* 20-bit PC-relative jump offset. */ 234 HOWTO (R_RISCV_JAL, /* type */ 235 0, /* rightshift */ 236 2, /* size (0 = byte, 1 = short, 2 = long) */ 237 32, /* bitsize */ 238 TRUE, /* pc_relative */ 239 0, /* bitpos */ 240 complain_overflow_dont, /* complain_on_overflow */ 241 /* This needs complex overflow 242 detection, because the upper 36 243 bits must match the PC + 4. */ 244 bfd_elf_generic_reloc, /* special_function */ 245 "R_RISCV_JAL", /* name */ 246 FALSE, /* partial_inplace */ 247 0, /* src_mask */ 248 ENCODE_UJTYPE_IMM(-1U), /* dst_mask */ 249 TRUE), /* pcrel_offset */ 250 251 /* 32-bit PC-relative function call (AUIPC/JALR). */ 252 HOWTO (R_RISCV_CALL, /* type */ 253 0, /* rightshift */ 254 2, /* size (0 = byte, 1 = short, 2 = long) */ 255 64, /* bitsize */ 256 TRUE, /* pc_relative */ 257 0, /* bitpos */ 258 complain_overflow_dont, /* complain_on_overflow */ 259 bfd_elf_generic_reloc, /* special_function */ 260 "R_RISCV_CALL", /* name */ 261 FALSE, /* partial_inplace */ 262 0, /* src_mask */ 263 ENCODE_UTYPE_IMM(-1U) | ((bfd_vma) ENCODE_ITYPE_IMM(-1U) << 32), /* dst_mask */ 264 TRUE), /* pcrel_offset */ 265 266 /* 32-bit PC-relative function call (AUIPC/JALR). */ 267 HOWTO (R_RISCV_CALL_PLT, /* type */ 268 0, /* rightshift */ 269 2, /* size (0 = byte, 1 = short, 2 = long) */ 270 64, /* bitsize */ 271 TRUE, /* pc_relative */ 272 0, /* bitpos */ 273 complain_overflow_dont, /* complain_on_overflow */ 274 bfd_elf_generic_reloc, /* special_function */ 275 "R_RISCV_CALL_PLT", /* name */ 276 FALSE, /* partial_inplace */ 277 0, /* src_mask */ 278 ENCODE_UTYPE_IMM(-1U) | ((bfd_vma) ENCODE_ITYPE_IMM(-1U) << 32), /* dst_mask */ 279 TRUE), /* pcrel_offset */ 280 281 /* High 20 bits of 32-bit PC-relative GOT access. */ 282 HOWTO (R_RISCV_GOT_HI20, /* type */ 283 0, /* rightshift */ 284 2, /* size (0 = byte, 1 = short, 2 = long) */ 285 32, /* bitsize */ 286 TRUE, /* pc_relative */ 287 0, /* bitpos */ 288 complain_overflow_dont, /* complain_on_overflow */ 289 bfd_elf_generic_reloc, /* special_function */ 290 "R_RISCV_GOT_HI20", /* name */ 291 FALSE, /* partial_inplace */ 292 0, /* src_mask */ 293 ENCODE_UTYPE_IMM(-1U), /* dst_mask */ 294 FALSE), /* pcrel_offset */ 295 296 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */ 297 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */ 298 0, /* rightshift */ 299 2, /* size (0 = byte, 1 = short, 2 = long) */ 300 32, /* bitsize */ 301 TRUE, /* pc_relative */ 302 0, /* bitpos */ 303 complain_overflow_dont, /* complain_on_overflow */ 304 bfd_elf_generic_reloc, /* special_function */ 305 "R_RISCV_TLS_GOT_HI20", /* name */ 306 FALSE, /* partial_inplace */ 307 0, /* src_mask */ 308 ENCODE_UTYPE_IMM(-1U), /* dst_mask */ 309 FALSE), /* pcrel_offset */ 310 311 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */ 312 HOWTO (R_RISCV_TLS_GD_HI20, /* type */ 313 0, /* rightshift */ 314 2, /* size (0 = byte, 1 = short, 2 = long) */ 315 32, /* bitsize */ 316 TRUE, /* pc_relative */ 317 0, /* bitpos */ 318 complain_overflow_dont, /* complain_on_overflow */ 319 bfd_elf_generic_reloc, /* special_function */ 320 "R_RISCV_TLS_GD_HI20", /* name */ 321 FALSE, /* partial_inplace */ 322 0, /* src_mask */ 323 ENCODE_UTYPE_IMM(-1U), /* dst_mask */ 324 FALSE), /* pcrel_offset */ 325 326 /* High 20 bits of 32-bit PC-relative reference. */ 327 HOWTO (R_RISCV_PCREL_HI20, /* type */ 328 0, /* rightshift */ 329 2, /* size (0 = byte, 1 = short, 2 = long) */ 330 32, /* bitsize */ 331 TRUE, /* pc_relative */ 332 0, /* bitpos */ 333 complain_overflow_dont, /* complain_on_overflow */ 334 bfd_elf_generic_reloc, /* special_function */ 335 "R_RISCV_PCREL_HI20", /* name */ 336 FALSE, /* partial_inplace */ 337 0, /* src_mask */ 338 ENCODE_UTYPE_IMM(-1U), /* dst_mask */ 339 TRUE), /* pcrel_offset */ 340 341 /* Low 12 bits of a 32-bit PC-relative load or add. */ 342 HOWTO (R_RISCV_PCREL_LO12_I, /* type */ 343 0, /* rightshift */ 344 2, /* size (0 = byte, 1 = short, 2 = long) */ 345 32, /* bitsize */ 346 FALSE, /* pc_relative */ 347 0, /* bitpos */ 348 complain_overflow_dont, /* complain_on_overflow */ 349 bfd_elf_generic_reloc, /* special_function */ 350 "R_RISCV_PCREL_LO12_I",/* name */ 351 FALSE, /* partial_inplace */ 352 0, /* src_mask */ 353 ENCODE_ITYPE_IMM(-1U), /* dst_mask */ 354 FALSE), /* pcrel_offset */ 355 356 /* Low 12 bits of a 32-bit PC-relative store. */ 357 HOWTO (R_RISCV_PCREL_LO12_S, /* type */ 358 0, /* rightshift */ 359 2, /* size (0 = byte, 1 = short, 2 = long) */ 360 32, /* bitsize */ 361 FALSE, /* pc_relative */ 362 0, /* bitpos */ 363 complain_overflow_dont, /* complain_on_overflow */ 364 bfd_elf_generic_reloc, /* special_function */ 365 "R_RISCV_PCREL_LO12_S",/* name */ 366 FALSE, /* partial_inplace */ 367 0, /* src_mask */ 368 ENCODE_STYPE_IMM(-1U), /* dst_mask */ 369 FALSE), /* pcrel_offset */ 370 371 /* High 20 bits of 32-bit absolute address. */ 372 HOWTO (R_RISCV_HI20, /* type */ 373 0, /* rightshift */ 374 2, /* size (0 = byte, 1 = short, 2 = long) */ 375 32, /* bitsize */ 376 FALSE, /* pc_relative */ 377 0, /* bitpos */ 378 complain_overflow_dont, /* complain_on_overflow */ 379 bfd_elf_generic_reloc, /* special_function */ 380 "R_RISCV_HI20", /* name */ 381 FALSE, /* partial_inplace */ 382 0, /* src_mask */ 383 ENCODE_UTYPE_IMM(-1U), /* dst_mask */ 384 FALSE), /* pcrel_offset */ 385 386 /* High 12 bits of 32-bit load or add. */ 387 HOWTO (R_RISCV_LO12_I, /* type */ 388 0, /* rightshift */ 389 2, /* size (0 = byte, 1 = short, 2 = long) */ 390 32, /* bitsize */ 391 FALSE, /* pc_relative */ 392 0, /* bitpos */ 393 complain_overflow_dont, /* complain_on_overflow */ 394 bfd_elf_generic_reloc, /* special_function */ 395 "R_RISCV_LO12_I", /* name */ 396 FALSE, /* partial_inplace */ 397 0, /* src_mask */ 398 ENCODE_ITYPE_IMM(-1U), /* dst_mask */ 399 FALSE), /* pcrel_offset */ 400 401 /* High 12 bits of 32-bit store. */ 402 HOWTO (R_RISCV_LO12_S, /* type */ 403 0, /* rightshift */ 404 2, /* size (0 = byte, 1 = short, 2 = long) */ 405 32, /* bitsize */ 406 FALSE, /* pc_relative */ 407 0, /* bitpos */ 408 complain_overflow_dont, /* complain_on_overflow */ 409 bfd_elf_generic_reloc, /* special_function */ 410 "R_RISCV_LO12_S", /* name */ 411 FALSE, /* partial_inplace */ 412 0, /* src_mask */ 413 ENCODE_STYPE_IMM(-1U), /* dst_mask */ 414 FALSE), /* pcrel_offset */ 415 416 /* High 20 bits of TLS LE thread pointer offset. */ 417 HOWTO (R_RISCV_TPREL_HI20, /* type */ 418 0, /* rightshift */ 419 2, /* size (0 = byte, 1 = short, 2 = long) */ 420 32, /* bitsize */ 421 FALSE, /* pc_relative */ 422 0, /* bitpos */ 423 complain_overflow_signed, /* complain_on_overflow */ 424 bfd_elf_generic_reloc, /* special_function */ 425 "R_RISCV_TPREL_HI20", /* name */ 426 TRUE, /* partial_inplace */ 427 0, /* src_mask */ 428 ENCODE_UTYPE_IMM(-1U), /* dst_mask */ 429 FALSE), /* pcrel_offset */ 430 431 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */ 432 HOWTO (R_RISCV_TPREL_LO12_I, /* type */ 433 0, /* rightshift */ 434 2, /* size (0 = byte, 1 = short, 2 = long) */ 435 32, /* bitsize */ 436 FALSE, /* pc_relative */ 437 0, /* bitpos */ 438 complain_overflow_signed, /* complain_on_overflow */ 439 bfd_elf_generic_reloc, /* special_function */ 440 "R_RISCV_TPREL_LO12_I",/* name */ 441 FALSE, /* partial_inplace */ 442 0, /* src_mask */ 443 ENCODE_ITYPE_IMM(-1U), /* dst_mask */ 444 FALSE), /* pcrel_offset */ 445 446 /* Low 12 bits of TLS LE thread pointer offset for stores. */ 447 HOWTO (R_RISCV_TPREL_LO12_S, /* type */ 448 0, /* rightshift */ 449 2, /* size (0 = byte, 1 = short, 2 = long) */ 450 32, /* bitsize */ 451 FALSE, /* pc_relative */ 452 0, /* bitpos */ 453 complain_overflow_signed, /* complain_on_overflow */ 454 bfd_elf_generic_reloc, /* special_function */ 455 "R_RISCV_TPREL_LO12_S",/* name */ 456 FALSE, /* partial_inplace */ 457 0, /* src_mask */ 458 ENCODE_STYPE_IMM(-1U), /* dst_mask */ 459 FALSE), /* pcrel_offset */ 460 461 /* TLS LE thread pointer usage. */ 462 HOWTO (R_RISCV_TPREL_ADD, /* type */ 463 0, /* rightshift */ 464 2, /* size (0 = byte, 1 = short, 2 = long) */ 465 32, /* bitsize */ 466 FALSE, /* pc_relative */ 467 0, /* bitpos */ 468 complain_overflow_dont,/* complain_on_overflow */ 469 bfd_elf_generic_reloc, /* special_function */ 470 "R_RISCV_TPREL_ADD", /* name */ 471 TRUE, /* partial_inplace */ 472 0, /* src_mask */ 473 0, /* dst_mask */ 474 FALSE), /* pcrel_offset */ 475 476 /* 8-bit in-place addition, for local label subtraction. */ 477 HOWTO (R_RISCV_ADD8, /* type */ 478 0, /* rightshift */ 479 0, /* size (0 = byte, 1 = short, 2 = long) */ 480 32, /* bitsize */ 481 FALSE, /* pc_relative */ 482 0, /* bitpos */ 483 complain_overflow_dont, /* complain_on_overflow */ 484 bfd_elf_generic_reloc, /* special_function */ 485 "R_RISCV_ADD8", /* name */ 486 FALSE, /* partial_inplace */ 487 0, /* src_mask */ 488 MINUS_ONE, /* dst_mask */ 489 FALSE), /* pcrel_offset */ 490 491 /* 16-bit in-place addition, for local label subtraction. */ 492 HOWTO (R_RISCV_ADD16, /* type */ 493 0, /* rightshift */ 494 1, /* size (0 = byte, 1 = short, 2 = long) */ 495 16, /* bitsize */ 496 FALSE, /* pc_relative */ 497 0, /* bitpos */ 498 complain_overflow_dont, /* complain_on_overflow */ 499 bfd_elf_generic_reloc, /* special_function */ 500 "R_RISCV_ADD16", /* name */ 501 FALSE, /* partial_inplace */ 502 0, /* src_mask */ 503 MINUS_ONE, /* dst_mask */ 504 FALSE), /* pcrel_offset */ 505 506 /* 32-bit in-place addition, for local label subtraction. */ 507 HOWTO (R_RISCV_ADD32, /* type */ 508 0, /* rightshift */ 509 2, /* size (0 = byte, 1 = short, 2 = long) */ 510 32, /* bitsize */ 511 FALSE, /* pc_relative */ 512 0, /* bitpos */ 513 complain_overflow_dont, /* complain_on_overflow */ 514 bfd_elf_generic_reloc, /* special_function */ 515 "R_RISCV_ADD32", /* name */ 516 FALSE, /* partial_inplace */ 517 0, /* src_mask */ 518 MINUS_ONE, /* dst_mask */ 519 FALSE), /* pcrel_offset */ 520 521 /* 64-bit in-place addition, for local label subtraction. */ 522 HOWTO (R_RISCV_ADD64, /* type */ 523 0, /* rightshift */ 524 4, /* size (0 = byte, 1 = short, 2 = long) */ 525 64, /* bitsize */ 526 FALSE, /* pc_relative */ 527 0, /* bitpos */ 528 complain_overflow_dont, /* complain_on_overflow */ 529 bfd_elf_generic_reloc, /* special_function */ 530 "R_RISCV_ADD64", /* name */ 531 FALSE, /* partial_inplace */ 532 0, /* src_mask */ 533 MINUS_ONE, /* dst_mask */ 534 FALSE), /* pcrel_offset */ 535 536 /* 8-bit in-place addition, for local label subtraction. */ 537 HOWTO (R_RISCV_SUB8, /* type */ 538 0, /* rightshift */ 539 0, /* size (0 = byte, 1 = short, 2 = long) */ 540 8, /* bitsize */ 541 FALSE, /* pc_relative */ 542 0, /* bitpos */ 543 complain_overflow_dont, /* complain_on_overflow */ 544 bfd_elf_generic_reloc, /* special_function */ 545 "R_RISCV_SUB8", /* name */ 546 FALSE, /* partial_inplace */ 547 0, /* src_mask */ 548 MINUS_ONE, /* dst_mask */ 549 FALSE), /* pcrel_offset */ 550 551 /* 16-bit in-place addition, for local label subtraction. */ 552 HOWTO (R_RISCV_SUB16, /* type */ 553 0, /* rightshift */ 554 1, /* size (0 = byte, 1 = short, 2 = long) */ 555 16, /* bitsize */ 556 FALSE, /* pc_relative */ 557 0, /* bitpos */ 558 complain_overflow_dont, /* complain_on_overflow */ 559 bfd_elf_generic_reloc, /* special_function */ 560 "R_RISCV_SUB16", /* name */ 561 FALSE, /* partial_inplace */ 562 0, /* src_mask */ 563 MINUS_ONE, /* dst_mask */ 564 FALSE), /* pcrel_offset */ 565 566 /* 32-bit in-place addition, for local label subtraction. */ 567 HOWTO (R_RISCV_SUB32, /* type */ 568 0, /* rightshift */ 569 2, /* size (0 = byte, 1 = short, 2 = long) */ 570 32, /* bitsize */ 571 FALSE, /* pc_relative */ 572 0, /* bitpos */ 573 complain_overflow_dont, /* complain_on_overflow */ 574 bfd_elf_generic_reloc, /* special_function */ 575 "R_RISCV_SUB32", /* name */ 576 FALSE, /* partial_inplace */ 577 0, /* src_mask */ 578 MINUS_ONE, /* dst_mask */ 579 FALSE), /* pcrel_offset */ 580 581 /* 64-bit in-place addition, for local label subtraction. */ 582 HOWTO (R_RISCV_SUB64, /* type */ 583 0, /* rightshift */ 584 4, /* size (0 = byte, 1 = short, 2 = long) */ 585 64, /* bitsize */ 586 FALSE, /* pc_relative */ 587 0, /* bitpos */ 588 complain_overflow_dont, /* complain_on_overflow */ 589 bfd_elf_generic_reloc, /* special_function */ 590 "R_RISCV_SUB64", /* name */ 591 FALSE, /* partial_inplace */ 592 0, /* src_mask */ 593 MINUS_ONE, /* dst_mask */ 594 FALSE), /* pcrel_offset */ 595 596 /* GNU extension to record C++ vtable hierarchy */ 597 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */ 598 0, /* rightshift */ 599 4, /* size (0 = byte, 1 = short, 2 = long) */ 600 0, /* bitsize */ 601 FALSE, /* pc_relative */ 602 0, /* bitpos */ 603 complain_overflow_dont,/* complain_on_overflow */ 604 NULL, /* special_function */ 605 "R_RISCV_GNU_VTINHERIT", /* name */ 606 FALSE, /* partial_inplace */ 607 0, /* src_mask */ 608 0, /* dst_mask */ 609 FALSE), /* pcrel_offset */ 610 611 /* GNU extension to record C++ vtable member usage */ 612 HOWTO (R_RISCV_GNU_VTENTRY, /* type */ 613 0, /* rightshift */ 614 4, /* size (0 = byte, 1 = short, 2 = long) */ 615 0, /* bitsize */ 616 FALSE, /* pc_relative */ 617 0, /* bitpos */ 618 complain_overflow_dont,/* complain_on_overflow */ 619 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 620 "R_RISCV_GNU_VTENTRY", /* name */ 621 FALSE, /* partial_inplace */ 622 0, /* src_mask */ 623 0, /* dst_mask */ 624 FALSE), /* pcrel_offset */ 625 626 /* Indicates an alignment statement. The addend field encodes how many 627 bytes of NOPs follow the statement. The desired alignment is the 628 addend rounded up to the next power of two. */ 629 HOWTO (R_RISCV_ALIGN, /* type */ 630 0, /* rightshift */ 631 2, /* size (0 = byte, 1 = short, 2 = long) */ 632 0, /* bitsize */ 633 FALSE, /* pc_relative */ 634 0, /* bitpos */ 635 complain_overflow_dont, /* complain_on_overflow */ 636 bfd_elf_generic_reloc, /* special_function */ 637 "R_RISCV_ALIGN", /* name */ 638 FALSE, /* partial_inplace */ 639 0, /* src_mask */ 640 0, /* dst_mask */ 641 TRUE), /* pcrel_offset */ 642 }; 643 644 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ 645 646 struct elf_reloc_map { 647 bfd_reloc_code_real_type bfd_val; 648 enum elf_riscv_reloc_type elf_val; 649 }; 650 651 static const struct elf_reloc_map riscv_reloc_map[] = 652 { 653 { BFD_RELOC_NONE, R_RISCV_NONE }, 654 { BFD_RELOC_32, R_RISCV_32 }, 655 { BFD_RELOC_64, R_RISCV_64 }, 656 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 }, 657 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 }, 658 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 }, 659 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 }, 660 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 }, 661 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 }, 662 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 }, 663 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 }, 664 { BFD_RELOC_CTOR, R_RISCV_64 }, 665 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH }, 666 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 }, 667 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I }, 668 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S }, 669 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I }, 670 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S }, 671 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL }, 672 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT }, 673 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 }, 674 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL }, 675 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 }, 676 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 }, 677 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 }, 678 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 }, 679 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 }, 680 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 }, 681 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 }, 682 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 }, 683 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD }, 684 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S }, 685 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I }, 686 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 }, 687 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 }, 688 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN }, 689 }; 690 691 /* Given a BFD reloc type, return a howto structure. */ 692 693 reloc_howto_type * 694 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 695 bfd_reloc_code_real_type code) 696 { 697 unsigned int i; 698 699 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++) 700 if (riscv_reloc_map[i].bfd_val == code) 701 return &howto_table[(int) riscv_reloc_map[i].elf_val]; 702 703 bfd_set_error (bfd_error_bad_value); 704 return NULL; 705 } 706 707 reloc_howto_type * 708 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 709 const char *r_name) 710 { 711 unsigned int i; 712 713 for (i = 0; i < ARRAY_SIZE (howto_table); i++) 714 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0) 715 return &howto_table[i]; 716 717 return NULL; 718 } 719 720 reloc_howto_type * 721 riscv_elf_rtype_to_howto (unsigned int r_type) 722 { 723 if ((unsigned int)r_type >= ARRAY_SIZE (howto_table)) 724 { 725 (*_bfd_error_handler)(_("unrecognized relocation (0x%x)"), r_type); 726 bfd_set_error (bfd_error_bad_value); 727 return NULL; 728 } 729 return &howto_table[r_type]; 730 } 731