1/* RISC-V disassembler 2 Copyright (C) 2011-2022 Free Software Foundation, Inc. 3 4 Contributed by Andrew Waterman (andrew@sifive.com). 5 Based on MIPS target. 6 7 This file is part of the GNU opcodes library. 8 9 This library 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, or (at your option) 12 any later version. 13 14 It is distributed in the hope that it will be useful, but WITHOUT 15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 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 "disassemble.h" 25#include "libiberty.h" 26#include "opcode/riscv.h" 27#include "opintl.h" 28#include "elf-bfd.h" 29#include "elf/riscv.h" 30#include "elfxx-riscv.h" 31 32#include <stdint.h> 33#include <ctype.h> 34 35static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; 36static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE; 37 38unsigned xlen = 0; 39 40static riscv_subset_list_t riscv_subsets; 41static riscv_parse_subset_t riscv_rps_dis = 42{ 43 &riscv_subsets, /* subset_list. */ 44 opcodes_error_handler,/* error_handler. */ 45 &xlen, /* xlen. */ 46 &default_isa_spec, /* isa_spec. */ 47 false, /* check_unknown_prefixed_ext. */ 48}; 49 50struct riscv_private_data 51{ 52 bfd_vma gp; 53 bfd_vma print_addr; 54 bfd_vma hi_addr[OP_MASK_RD + 1]; 55}; 56 57/* Used for mapping symbols. */ 58static int last_map_symbol = -1; 59static bfd_vma last_stop_offset = 0; 60enum riscv_seg_mstate last_map_state; 61 62static const char * const *riscv_gpr_names; 63static const char * const *riscv_fpr_names; 64 65/* If set, disassemble as most general instruction. */ 66static int no_aliases; 67 68static void 69set_default_riscv_dis_options (void) 70{ 71 riscv_gpr_names = riscv_gpr_names_abi; 72 riscv_fpr_names = riscv_fpr_names_abi; 73 no_aliases = 0; 74} 75 76static bool 77parse_riscv_dis_option_without_args (const char *option) 78{ 79 if (strcmp (option, "no-aliases") == 0) 80 no_aliases = 1; 81 else if (strcmp (option, "numeric") == 0) 82 { 83 riscv_gpr_names = riscv_gpr_names_numeric; 84 riscv_fpr_names = riscv_fpr_names_numeric; 85 } 86 else 87 return false; 88 return true; 89} 90 91static void 92parse_riscv_dis_option (const char *option) 93{ 94 char *equal, *value; 95 96 if (parse_riscv_dis_option_without_args (option)) 97 return; 98 99 equal = strchr (option, '='); 100 if (equal == NULL) 101 { 102 /* The option without '=' should be defined above. */ 103 opcodes_error_handler (_("unrecognized disassembler option: %s"), option); 104 return; 105 } 106 if (equal == option 107 || *(equal + 1) == '\0') 108 { 109 /* Invalid options with '=', no option name before '=', 110 and no value after '='. */ 111 opcodes_error_handler (_("unrecognized disassembler option with '=': %s"), 112 option); 113 return; 114 } 115 116 *equal = '\0'; 117 value = equal + 1; 118 if (strcmp (option, "priv-spec") == 0) 119 { 120 enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE; 121 const char *name = NULL; 122 123 RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec); 124 if (priv_spec == PRIV_SPEC_CLASS_NONE) 125 opcodes_error_handler (_("unknown privileged spec set by %s=%s"), 126 option, value); 127 else if (default_priv_spec == PRIV_SPEC_CLASS_NONE) 128 default_priv_spec = priv_spec; 129 else if (default_priv_spec != priv_spec) 130 { 131 RISCV_GET_PRIV_SPEC_NAME (name, default_priv_spec); 132 opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, " 133 "the elf privilege attribute is %s"), 134 option, value, name); 135 } 136 } 137 else 138 { 139 /* xgettext:c-format */ 140 opcodes_error_handler (_("unrecognized disassembler option: %s"), option); 141 } 142} 143 144static void 145parse_riscv_dis_options (const char *opts_in) 146{ 147 char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts; 148 149 set_default_riscv_dis_options (); 150 151 for ( ; opt_end != NULL; opt = opt_end + 1) 152 { 153 if ((opt_end = strchr (opt, ',')) != NULL) 154 *opt_end = 0; 155 parse_riscv_dis_option (opt); 156 } 157 158 free (opts); 159} 160 161/* Print one argument from an array. */ 162 163static void 164arg_print (struct disassemble_info *info, unsigned long val, 165 const char* const* array, size_t size) 166{ 167 const char *s = val >= size || array[val] == NULL ? "unknown" : array[val]; 168 (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s", s); 169} 170 171static void 172maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset, 173 int wide) 174{ 175 if (pd->hi_addr[base_reg] != (bfd_vma)-1) 176 { 177 pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset; 178 pd->hi_addr[base_reg] = -1; 179 } 180 else if (base_reg == X_GP && pd->gp != (bfd_vma)-1) 181 pd->print_addr = pd->gp + offset; 182 else if (base_reg == X_TP || base_reg == 0) 183 pd->print_addr = offset; 184 185 /* Sign-extend a 32-bit value to a 64-bit value. */ 186 if (wide) 187 pd->print_addr = (bfd_vma)(int32_t) pd->print_addr; 188} 189 190/* Print insn arguments for 32/64-bit code. */ 191 192static void 193print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info) 194{ 195 struct riscv_private_data *pd = info->private_data; 196 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1; 197 int rd = (l >> OP_SH_RD) & OP_MASK_RD; 198 fprintf_styled_ftype print = info->fprintf_styled_func; 199 const char *opargStart; 200 201 if (*oparg != '\0') 202 print (info->stream, dis_style_text, "\t"); 203 204 for (; *oparg != '\0'; oparg++) 205 { 206 opargStart = oparg; 207 switch (*oparg) 208 { 209 case 'C': /* RVC */ 210 switch (*++oparg) 211 { 212 case 's': /* RS1 x8-x15. */ 213 case 'w': /* RS1 x8-x15. */ 214 print (info->stream, dis_style_register, "%s", 215 riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]); 216 break; 217 case 't': /* RS2 x8-x15. */ 218 case 'x': /* RS2 x8-x15. */ 219 print (info->stream, dis_style_register, "%s", 220 riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); 221 break; 222 case 'U': /* RS1, constrained to equal RD. */ 223 print (info->stream, dis_style_register, 224 "%s", riscv_gpr_names[rd]); 225 break; 226 case 'c': /* RS1, constrained to equal sp. */ 227 print (info->stream, dis_style_register, "%s", 228 riscv_gpr_names[X_SP]); 229 break; 230 case 'V': /* RS2 */ 231 print (info->stream, dis_style_register, "%s", 232 riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]); 233 break; 234 case 'o': 235 case 'j': 236 if (((l & MASK_C_ADDI) == MATCH_C_ADDI) && rd != 0) 237 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 0); 238 if (info->mach == bfd_mach_riscv64 239 && ((l & MASK_C_ADDIW) == MATCH_C_ADDIW) && rd != 0) 240 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 1); 241 print (info->stream, dis_style_immediate, "%d", 242 (int)EXTRACT_CITYPE_IMM (l)); 243 break; 244 case 'k': 245 print (info->stream, dis_style_address_offset, "%d", 246 (int)EXTRACT_CLTYPE_LW_IMM (l)); 247 break; 248 case 'l': 249 print (info->stream, dis_style_address_offset, "%d", 250 (int)EXTRACT_CLTYPE_LD_IMM (l)); 251 break; 252 case 'm': 253 print (info->stream, dis_style_address_offset, "%d", 254 (int)EXTRACT_CITYPE_LWSP_IMM (l)); 255 break; 256 case 'n': 257 print (info->stream, dis_style_address_offset, "%d", 258 (int)EXTRACT_CITYPE_LDSP_IMM (l)); 259 break; 260 case 'K': 261 print (info->stream, dis_style_immediate, "%d", 262 (int)EXTRACT_CIWTYPE_ADDI4SPN_IMM (l)); 263 break; 264 case 'L': 265 print (info->stream, dis_style_immediate, "%d", 266 (int)EXTRACT_CITYPE_ADDI16SP_IMM (l)); 267 break; 268 case 'M': 269 print (info->stream, dis_style_address_offset, "%d", 270 (int)EXTRACT_CSSTYPE_SWSP_IMM (l)); 271 break; 272 case 'N': 273 print (info->stream, dis_style_address_offset, "%d", 274 (int)EXTRACT_CSSTYPE_SDSP_IMM (l)); 275 break; 276 case 'p': 277 info->target = EXTRACT_CBTYPE_IMM (l) + pc; 278 (*info->print_address_func) (info->target, info); 279 break; 280 case 'a': 281 info->target = EXTRACT_CJTYPE_IMM (l) + pc; 282 (*info->print_address_func) (info->target, info); 283 break; 284 case 'u': 285 print (info->stream, dis_style_immediate, "0x%x", 286 (int)(EXTRACT_CITYPE_IMM (l) & (RISCV_BIGIMM_REACH-1))); 287 break; 288 case '>': 289 print (info->stream, dis_style_immediate, "0x%x", 290 (int)EXTRACT_CITYPE_IMM (l) & 0x3f); 291 break; 292 case '<': 293 print (info->stream, dis_style_immediate, "0x%x", 294 (int)EXTRACT_CITYPE_IMM (l) & 0x1f); 295 break; 296 case 'T': /* Floating-point RS2. */ 297 print (info->stream, dis_style_register, "%s", 298 riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]); 299 break; 300 case 'D': /* Floating-point RS2 x8-x15. */ 301 print (info->stream, dis_style_register, "%s", 302 riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); 303 break; 304 } 305 break; 306 307 case 'V': /* RVV */ 308 switch (*++oparg) 309 { 310 case 'd': 311 case 'f': 312 print (info->stream, dis_style_register, "%s", 313 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]); 314 break; 315 case 'e': 316 if (!EXTRACT_OPERAND (VWD, l)) 317 print (info->stream, dis_style_register, "%s", 318 riscv_gpr_names[0]); 319 else 320 print (info->stream, dis_style_register, "%s", 321 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]); 322 break; 323 case 's': 324 print (info->stream, dis_style_register, "%s", 325 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS1, l)]); 326 break; 327 case 't': 328 case 'u': /* VS1 == VS2 already verified at this point. */ 329 case 'v': /* VD == VS1 == VS2 already verified at this point. */ 330 print (info->stream, dis_style_register, "%s", 331 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]); 332 break; 333 case '0': 334 print (info->stream, dis_style_register, "%s", 335 riscv_vecr_names_numeric[0]); 336 break; 337 case 'b': 338 case 'c': 339 { 340 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l) 341 : EXTRACT_RVV_VC_IMM (l); 342 unsigned int imm_vlmul = EXTRACT_OPERAND (VLMUL, imm); 343 unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm); 344 unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm); 345 unsigned int imm_vma = EXTRACT_OPERAND (VMA, imm); 346 unsigned int imm_vtype_res = (imm >> 8); 347 348 if (imm_vsew < ARRAY_SIZE (riscv_vsew) 349 && imm_vlmul < ARRAY_SIZE (riscv_vlmul) 350 && imm_vta < ARRAY_SIZE (riscv_vta) 351 && imm_vma < ARRAY_SIZE (riscv_vma) 352 && !imm_vtype_res 353 && riscv_vsew[imm_vsew] != NULL 354 && riscv_vlmul[imm_vlmul] != NULL) 355 print (info->stream, dis_style_text, "%s,%s,%s,%s", 356 riscv_vsew[imm_vsew], 357 riscv_vlmul[imm_vlmul], riscv_vta[imm_vta], 358 riscv_vma[imm_vma]); 359 else 360 print (info->stream, dis_style_immediate, "%d", imm); 361 } 362 break; 363 case 'i': 364 print (info->stream, dis_style_immediate, "%d", 365 (int)EXTRACT_RVV_VI_IMM (l)); 366 break; 367 case 'j': 368 print (info->stream, dis_style_immediate, "%d", 369 (int)EXTRACT_RVV_VI_UIMM (l)); 370 break; 371 case 'k': 372 print (info->stream, dis_style_immediate, "%d", 373 (int)EXTRACT_RVV_OFFSET (l)); 374 break; 375 case 'm': 376 if (! EXTRACT_OPERAND (VMASK, l)) 377 print (info->stream, dis_style_register, ",%s", 378 riscv_vecm_names_numeric[0]); 379 break; 380 } 381 break; 382 383 case ',': 384 case '(': 385 case ')': 386 case '[': 387 case ']': 388 print (info->stream, dis_style_text, "%c", *oparg); 389 break; 390 391 case '0': 392 /* Only print constant 0 if it is the last argument. */ 393 if (!oparg[1]) 394 print (info->stream, dis_style_immediate, "0"); 395 break; 396 397 case 'b': 398 case 's': 399 if ((l & MASK_JALR) == MATCH_JALR) 400 maybe_print_address (pd, rs1, 0, 0); 401 print (info->stream, dis_style_register, "%s", riscv_gpr_names[rs1]); 402 break; 403 404 case 't': 405 print (info->stream, dis_style_register, "%s", 406 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]); 407 break; 408 409 case 'u': 410 print (info->stream, dis_style_immediate, "0x%x", 411 (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS); 412 break; 413 414 case 'm': 415 arg_print (info, EXTRACT_OPERAND (RM, l), 416 riscv_rm, ARRAY_SIZE (riscv_rm)); 417 break; 418 419 case 'P': 420 arg_print (info, EXTRACT_OPERAND (PRED, l), 421 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ)); 422 break; 423 424 case 'Q': 425 arg_print (info, EXTRACT_OPERAND (SUCC, l), 426 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ)); 427 break; 428 429 case 'o': 430 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0); 431 /* Fall through. */ 432 case 'j': 433 if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0) 434 || (l & MASK_JALR) == MATCH_JALR) 435 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0); 436 if (info->mach == bfd_mach_riscv64 437 && ((l & MASK_ADDIW) == MATCH_ADDIW) && rs1 != 0) 438 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 1); 439 print (info->stream, dis_style_immediate, "%d", 440 (int)EXTRACT_ITYPE_IMM (l)); 441 break; 442 443 case 'q': 444 maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l), 0); 445 print (info->stream, dis_style_address_offset, "%d", 446 (int)EXTRACT_STYPE_IMM (l)); 447 break; 448 449 case 'f': 450 print (info->stream, dis_style_address_offset, "%d", 451 (int)EXTRACT_STYPE_IMM (l)); 452 break; 453 454 case 'a': 455 info->target = EXTRACT_JTYPE_IMM (l) + pc; 456 (*info->print_address_func) (info->target, info); 457 break; 458 459 case 'p': 460 info->target = EXTRACT_BTYPE_IMM (l) + pc; 461 (*info->print_address_func) (info->target, info); 462 break; 463 464 case 'd': 465 if ((l & MASK_AUIPC) == MATCH_AUIPC) 466 pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l); 467 else if ((l & MASK_LUI) == MATCH_LUI) 468 pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l); 469 else if ((l & MASK_C_LUI) == MATCH_C_LUI) 470 pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l); 471 print (info->stream, dis_style_register, "%s", riscv_gpr_names[rd]); 472 break; 473 474 case 'y': 475 print (info->stream, dis_style_text, "0x%x", 476 (int)EXTRACT_OPERAND (BS, l)); 477 break; 478 479 case 'z': 480 print (info->stream, dis_style_register, "%s", riscv_gpr_names[0]); 481 break; 482 483 case '>': 484 print (info->stream, dis_style_immediate, "0x%x", 485 (int)EXTRACT_OPERAND (SHAMT, l)); 486 break; 487 488 case '<': 489 print (info->stream, dis_style_immediate, "0x%x", 490 (int)EXTRACT_OPERAND (SHAMTW, l)); 491 break; 492 493 case 'S': 494 case 'U': 495 print (info->stream, dis_style_register, "%s", riscv_fpr_names[rs1]); 496 break; 497 498 case 'T': 499 print (info->stream, dis_style_register, "%s", 500 riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]); 501 break; 502 503 case 'D': 504 print (info->stream, dis_style_register, "%s", riscv_fpr_names[rd]); 505 break; 506 507 case 'R': 508 print (info->stream, dis_style_register, "%s", 509 riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]); 510 break; 511 512 case 'E': 513 { 514 static const char *riscv_csr_hash[4096]; /* Total 2^12 CSRs. */ 515 static bool init_csr = false; 516 unsigned int csr = EXTRACT_OPERAND (CSR, l); 517 518 if (!init_csr) 519 { 520 unsigned int i; 521 for (i = 0; i < 4096; i++) 522 riscv_csr_hash[i] = NULL; 523 524 /* Set to the newest privileged version. */ 525 if (default_priv_spec == PRIV_SPEC_CLASS_NONE) 526 default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1; 527 528#define DECLARE_CSR(name, num, class, define_version, abort_version) \ 529 if (riscv_csr_hash[num] == NULL \ 530 && ((define_version == PRIV_SPEC_CLASS_NONE \ 531 && abort_version == PRIV_SPEC_CLASS_NONE) \ 532 || (default_priv_spec >= define_version \ 533 && default_priv_spec < abort_version))) \ 534 riscv_csr_hash[num] = #name; 535#define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \ 536 DECLARE_CSR (name, num, class, define_version, abort_version) 537#include "opcode/riscv-opc.h" 538#undef DECLARE_CSR 539 } 540 541 if (riscv_csr_hash[csr] != NULL) 542 print (info->stream, dis_style_text, "%s", riscv_csr_hash[csr]); 543 else 544 print (info->stream, dis_style_text, "0x%x", csr); 545 break; 546 } 547 548 case 'Y': 549 print (info->stream, dis_style_text, "0x%x", 550 (int) EXTRACT_OPERAND (RNUM, l)); 551 break; 552 553 case 'Z': 554 print (info->stream, dis_style_text, "%d", rs1); 555 break; 556 557 default: 558 /* xgettext:c-format */ 559 print (info->stream, dis_style_text, 560 _("# internal error, undefined modifier (%c)"), 561 *opargStart); 562 return; 563 } 564 } 565} 566 567/* Print the RISC-V instruction at address MEMADDR in debugged memory, 568 on using INFO. Returns length of the instruction, in bytes. 569 BIGENDIAN must be 1 if this is big-endian code, 0 if 570 this is little-endian code. */ 571 572static int 573riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info) 574{ 575 const struct riscv_opcode *op; 576 static bool init = 0; 577 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1]; 578 struct riscv_private_data *pd; 579 int insnlen; 580 581#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP)) 582 583 /* Build a hash table to shorten the search time. */ 584 if (! init) 585 { 586 for (op = riscv_opcodes; op->name; op++) 587 if (!riscv_hash[OP_HASH_IDX (op->match)]) 588 riscv_hash[OP_HASH_IDX (op->match)] = op; 589 590 init = 1; 591 } 592 593 if (info->private_data == NULL) 594 { 595 int i; 596 597 pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data)); 598 pd->gp = -1; 599 pd->print_addr = -1; 600 for (i = 0; i < (int)ARRAY_SIZE (pd->hi_addr); i++) 601 pd->hi_addr[i] = -1; 602 603 for (i = 0; i < info->symtab_size; i++) 604 if (strcmp (bfd_asymbol_name (info->symtab[i]), RISCV_GP_SYMBOL) == 0) 605 pd->gp = bfd_asymbol_value (info->symtab[i]); 606 } 607 else 608 pd = info->private_data; 609 610 insnlen = riscv_insn_length (word); 611 612 /* RISC-V instructions are always little-endian. */ 613 info->endian_code = BFD_ENDIAN_LITTLE; 614 615 info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2; 616 info->bytes_per_line = 8; 617 /* We don't support constant pools, so this must be code. */ 618 info->display_endian = info->endian_code; 619 info->insn_info_valid = 1; 620 info->branch_delay_insns = 0; 621 info->data_size = 0; 622 info->insn_type = dis_nonbranch; 623 info->target = 0; 624 info->target2 = 0; 625 626 op = riscv_hash[OP_HASH_IDX (word)]; 627 if (op != NULL) 628 { 629 /* If XLEN is not known, get its value from the ELF class. */ 630 if (info->mach == bfd_mach_riscv64) 631 xlen = 64; 632 else if (info->mach == bfd_mach_riscv32) 633 xlen = 32; 634 else if (info->section != NULL) 635 { 636 Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); 637 xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; 638 } 639 640 /* If arch has ZFINX flags, use gpr for disassemble. */ 641 if(riscv_subset_supports (&riscv_rps_dis, "zfinx")) 642 riscv_fpr_names = riscv_gpr_names; 643 644 for (; op->name; op++) 645 { 646 /* Does the opcode match? */ 647 if (! (op->match_func) (op, word)) 648 continue; 649 /* Is this a pseudo-instruction and may we print it as such? */ 650 if (no_aliases && (op->pinfo & INSN_ALIAS)) 651 continue; 652 /* Is this instruction restricted to a certain value of XLEN? */ 653 if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen)) 654 continue; 655 656 if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class)) 657 continue; 658 659 /* It's a match. */ 660 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 661 "%s", op->name); 662 print_insn_args (op->args, word, memaddr, info); 663 664 /* Try to disassemble multi-instruction addressing sequences. */ 665 if (pd->print_addr != (bfd_vma)-1) 666 { 667 info->target = pd->print_addr; 668 (*info->fprintf_styled_func) 669 (info->stream, dis_style_comment_start, " # "); 670 (*info->print_address_func) (info->target, info); 671 pd->print_addr = -1; 672 } 673 674 /* Finish filling out insn_info fields. */ 675 switch (op->pinfo & INSN_TYPE) 676 { 677 case INSN_BRANCH: 678 info->insn_type = dis_branch; 679 break; 680 case INSN_CONDBRANCH: 681 info->insn_type = dis_condbranch; 682 break; 683 case INSN_JSR: 684 info->insn_type = dis_jsr; 685 break; 686 case INSN_DREF: 687 info->insn_type = dis_dref; 688 break; 689 default: 690 break; 691 } 692 693 if (op->pinfo & INSN_DATA_SIZE) 694 { 695 int size = ((op->pinfo & INSN_DATA_SIZE) 696 >> INSN_DATA_SIZE_SHIFT); 697 info->data_size = 1 << (size - 1); 698 } 699 700 return insnlen; 701 } 702 } 703 704 /* We did not find a match, so just print the instruction bits. */ 705 info->insn_type = dis_noninsn; 706 switch (insnlen) 707 { 708 case 2: 709 case 4: 710 case 8: 711 (*info->fprintf_styled_func) 712 (info->stream, dis_style_assembler_directive, ".%dbyte\t", insnlen); 713 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 714 "0x%llx", (unsigned long long) word); 715 break; 716 default: 717 { 718 int i; 719 (*info->fprintf_styled_func) 720 (info->stream, dis_style_assembler_directive, ".byte\t"); 721 for (i = 0; i < insnlen; ++i) 722 { 723 if (i > 0) 724 (*info->fprintf_styled_func) (info->stream, dis_style_text, 725 ", "); 726 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 727 "0x%02x", 728 (unsigned int) (word & 0xff)); 729 word >>= 8; 730 } 731 } 732 break; 733 } 734 return insnlen; 735} 736 737/* Return true if we find the suitable mapping symbol, 738 and also update the STATE. Otherwise, return false. */ 739 740static bool 741riscv_get_map_state (int n, 742 enum riscv_seg_mstate *state, 743 struct disassemble_info *info) 744{ 745 const char *name; 746 747 /* If the symbol is in a different section, ignore it. */ 748 if (info->section != NULL 749 && info->section != info->symtab[n]->section) 750 return false; 751 752 name = bfd_asymbol_name(info->symtab[n]); 753 if (strcmp (name, "$x") == 0) 754 *state = MAP_INSN; 755 else if (strcmp (name, "$d") == 0) 756 *state = MAP_DATA; 757 else 758 return false; 759 760 return true; 761} 762 763/* Check the sorted symbol table (sorted by the symbol value), find the 764 suitable mapping symbols. */ 765 766static enum riscv_seg_mstate 767riscv_search_mapping_symbol (bfd_vma memaddr, 768 struct disassemble_info *info) 769{ 770 enum riscv_seg_mstate mstate; 771 bool from_last_map_symbol; 772 bool found = false; 773 int symbol = -1; 774 int n; 775 776 /* Decide whether to print the data or instruction by default, in case 777 we can not find the corresponding mapping symbols. */ 778 mstate = MAP_DATA; 779 if ((info->section 780 && info->section->flags & SEC_CODE) 781 || !info->section) 782 mstate = MAP_INSN; 783 784 if (info->symtab_size == 0 785 || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour) 786 return mstate; 787 788 /* Reset the last_map_symbol if we start to dump a new section. */ 789 if (memaddr <= 0) 790 last_map_symbol = -1; 791 792 /* If the last stop offset is different from the current one, then 793 don't use the last_map_symbol to search. We usually reset the 794 info->stop_offset when handling a new section. */ 795 from_last_map_symbol = (last_map_symbol >= 0 796 && info->stop_offset == last_stop_offset); 797 798 /* Start scanning at the start of the function, or wherever 799 we finished last time. */ 800 n = info->symtab_pos + 1; 801 if (from_last_map_symbol && n >= last_map_symbol) 802 n = last_map_symbol; 803 804 /* Find the suitable mapping symbol to dump. */ 805 for (; n < info->symtab_size; n++) 806 { 807 bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 808 /* We have searched all possible symbols in the range. */ 809 if (addr > memaddr) 810 break; 811 if (riscv_get_map_state (n, &mstate, info)) 812 { 813 symbol = n; 814 found = true; 815 /* Do not stop searching, in case there are some mapping 816 symbols have the same value, but have different names. 817 Use the last one. */ 818 } 819 } 820 821 /* We can not find the suitable mapping symbol above. Therefore, we 822 look forwards and try to find it again, but don't go pass the start 823 of the section. Otherwise a data section without mapping symbols 824 can pick up a text mapping symbol of a preceeding section. */ 825 if (!found) 826 { 827 n = info->symtab_pos; 828 if (from_last_map_symbol && n >= last_map_symbol) 829 n = last_map_symbol; 830 831 for (; n >= 0; n--) 832 { 833 bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 834 /* We have searched all possible symbols in the range. */ 835 if (addr < (info->section ? info->section->vma : 0)) 836 break; 837 /* Stop searching once we find the closed mapping symbol. */ 838 if (riscv_get_map_state (n, &mstate, info)) 839 { 840 symbol = n; 841 found = true; 842 break; 843 } 844 } 845 } 846 847 /* Save the information for next use. */ 848 last_map_symbol = symbol; 849 last_stop_offset = info->stop_offset; 850 851 return mstate; 852} 853 854/* Decide which data size we should print. */ 855 856static bfd_vma 857riscv_data_length (bfd_vma memaddr, 858 disassemble_info *info) 859{ 860 bfd_vma length; 861 bool found = false; 862 863 length = 4; 864 if (info->symtab_size != 0 865 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour 866 && last_map_symbol >= 0) 867 { 868 int n; 869 enum riscv_seg_mstate m = MAP_NONE; 870 for (n = last_map_symbol + 1; n < info->symtab_size; n++) 871 { 872 bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 873 if (addr > memaddr 874 && riscv_get_map_state (n, &m, info)) 875 { 876 if (addr - memaddr < length) 877 length = addr - memaddr; 878 found = true; 879 break; 880 } 881 } 882 } 883 if (!found) 884 { 885 /* Do not set the length which exceeds the section size. */ 886 bfd_vma offset = info->section->vma + info->section->size; 887 offset -= memaddr; 888 length = (offset < length) ? offset : length; 889 } 890 length = length == 3 ? 2 : length; 891 return length; 892} 893 894/* Dump the data contents. */ 895 896static int 897riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED, 898 insn_t data, 899 disassemble_info *info) 900{ 901 info->display_endian = info->endian; 902 903 switch (info->bytes_per_chunk) 904 { 905 case 1: 906 info->bytes_per_line = 6; 907 (*info->fprintf_styled_func) 908 (info->stream, dis_style_assembler_directive, ".byte\t"); 909 (*info->fprintf_styled_func) 910 (info->stream, dis_style_assembler_directive, "0x%02llx", 911 (unsigned long long) data); 912 break; 913 case 2: 914 info->bytes_per_line = 8; 915 (*info->fprintf_styled_func) 916 (info->stream, dis_style_assembler_directive, ".short\t"); 917 (*info->fprintf_styled_func) 918 (info->stream, dis_style_immediate, "0x%04llx", 919 (unsigned long long) data); 920 break; 921 case 4: 922 info->bytes_per_line = 8; 923 (*info->fprintf_styled_func) 924 (info->stream, dis_style_assembler_directive, ".word\t"); 925 (*info->fprintf_styled_func) 926 (info->stream, dis_style_immediate, "0x%08llx", 927 (unsigned long long) data); 928 break; 929 case 8: 930 info->bytes_per_line = 8; 931 (*info->fprintf_styled_func) 932 (info->stream, dis_style_assembler_directive, ".dword\t"); 933 (*info->fprintf_styled_func) 934 (info->stream, dis_style_immediate, "0x%016llx", 935 (unsigned long long) data); 936 break; 937 default: 938 abort (); 939 } 940 return info->bytes_per_chunk; 941} 942 943int 944print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info) 945{ 946 bfd_byte packet[8]; 947 insn_t insn = 0; 948 bfd_vma dump_size; 949 int status; 950 enum riscv_seg_mstate mstate; 951 int (*riscv_disassembler) (bfd_vma, insn_t, struct disassemble_info *); 952 953 if (info->disassembler_options != NULL) 954 { 955 parse_riscv_dis_options (info->disassembler_options); 956 /* Avoid repeatedly parsing the options. */ 957 info->disassembler_options = NULL; 958 } 959 else if (riscv_gpr_names == NULL) 960 set_default_riscv_dis_options (); 961 962 mstate = riscv_search_mapping_symbol (memaddr, info); 963 /* Save the last mapping state. */ 964 last_map_state = mstate; 965 966 /* Set the size to dump. */ 967 if (mstate == MAP_DATA 968 && (info->flags & DISASSEMBLE_DATA) == 0) 969 { 970 dump_size = riscv_data_length (memaddr, info); 971 info->bytes_per_chunk = dump_size; 972 riscv_disassembler = riscv_disassemble_data; 973 } 974 else 975 { 976 /* Get the first 2-bytes to check the lenghth of instruction. */ 977 status = (*info->read_memory_func) (memaddr, packet, 2, info); 978 if (status != 0) 979 { 980 (*info->memory_error_func) (status, memaddr, info); 981 return status; 982 } 983 insn = (insn_t) bfd_getl16 (packet); 984 dump_size = riscv_insn_length (insn); 985 riscv_disassembler = riscv_disassemble_insn; 986 } 987 988 /* Fetch the instruction to dump. */ 989 status = (*info->read_memory_func) (memaddr, packet, dump_size, info); 990 if (status != 0) 991 { 992 (*info->memory_error_func) (status, memaddr, info); 993 return status; 994 } 995 insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false); 996 997 return (*riscv_disassembler) (memaddr, insn, info); 998} 999 1000disassembler_ftype 1001riscv_get_disassembler (bfd *abfd) 1002{ 1003 const char *default_arch = "rv64gc"; 1004 1005 if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour) 1006 { 1007 const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section; 1008 if (bfd_get_section_by_name (abfd, sec_name) != NULL) 1009 { 1010 obj_attribute *attr = elf_known_obj_attributes_proc (abfd); 1011 unsigned int Tag_a = Tag_RISCV_priv_spec; 1012 unsigned int Tag_b = Tag_RISCV_priv_spec_minor; 1013 unsigned int Tag_c = Tag_RISCV_priv_spec_revision; 1014 riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i, 1015 attr[Tag_b].i, 1016 attr[Tag_c].i, 1017 &default_priv_spec); 1018 default_arch = attr[Tag_RISCV_arch].s; 1019 } 1020 } 1021 1022 riscv_release_subset_list (&riscv_subsets); 1023 riscv_parse_subset (&riscv_rps_dis, default_arch); 1024 return print_insn_riscv; 1025} 1026 1027/* Prevent use of the fake labels that are generated as part of the DWARF 1028 and for relaxable relocations in the assembler. */ 1029 1030bool 1031riscv_symbol_is_valid (asymbol * sym, 1032 struct disassemble_info * info ATTRIBUTE_UNUSED) 1033{ 1034 const char * name; 1035 1036 if (sym == NULL) 1037 return false; 1038 1039 name = bfd_asymbol_name (sym); 1040 1041 return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0 1042 && !riscv_elf_is_mapping_symbols (name)); 1043} 1044 1045 1046/* Indices into option argument vector for options accepting an argument. 1047 Use RISCV_OPTION_ARG_NONE for options accepting no argument. */ 1048 1049typedef enum 1050{ 1051 RISCV_OPTION_ARG_NONE = -1, 1052 RISCV_OPTION_ARG_PRIV_SPEC, 1053 1054 RISCV_OPTION_ARG_COUNT 1055} riscv_option_arg_t; 1056 1057/* Valid RISCV disassembler options. */ 1058 1059static struct 1060{ 1061 const char *name; 1062 const char *description; 1063 riscv_option_arg_t arg; 1064} riscv_options[] = 1065{ 1066 { "numeric", 1067 N_("Print numeric register names, rather than ABI names."), 1068 RISCV_OPTION_ARG_NONE }, 1069 { "no-aliases", 1070 N_("Disassemble only into canonical instructions."), 1071 RISCV_OPTION_ARG_NONE }, 1072 { "priv-spec=", 1073 N_("Print the CSR according to the chosen privilege spec."), 1074 RISCV_OPTION_ARG_PRIV_SPEC } 1075}; 1076 1077/* Build the structure representing valid RISCV disassembler options. 1078 This is done dynamically for maintenance ease purpose; a static 1079 initializer would be unreadable. */ 1080 1081const disasm_options_and_args_t * 1082disassembler_options_riscv (void) 1083{ 1084 static disasm_options_and_args_t *opts_and_args; 1085 1086 if (opts_and_args == NULL) 1087 { 1088 size_t num_options = ARRAY_SIZE (riscv_options); 1089 size_t num_args = RISCV_OPTION_ARG_COUNT; 1090 disasm_option_arg_t *args; 1091 disasm_options_t *opts; 1092 size_t i, priv_spec_count; 1093 1094 args = XNEWVEC (disasm_option_arg_t, num_args + 1); 1095 1096 args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC"; 1097 priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_CLASS_NONE - 1; 1098 args[RISCV_OPTION_ARG_PRIV_SPEC].values 1099 = XNEWVEC (const char *, priv_spec_count + 1); 1100 for (i = 0; i < priv_spec_count; i++) 1101 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] 1102 = riscv_priv_specs[i].name; 1103 /* The array we return must be NULL terminated. */ 1104 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] = NULL; 1105 1106 /* The array we return must be NULL terminated. */ 1107 args[num_args].name = NULL; 1108 args[num_args].values = NULL; 1109 1110 opts_and_args = XNEW (disasm_options_and_args_t); 1111 opts_and_args->args = args; 1112 1113 opts = &opts_and_args->options; 1114 opts->name = XNEWVEC (const char *, num_options + 1); 1115 opts->description = XNEWVEC (const char *, num_options + 1); 1116 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1); 1117 for (i = 0; i < num_options; i++) 1118 { 1119 opts->name[i] = riscv_options[i].name; 1120 opts->description[i] = _(riscv_options[i].description); 1121 if (riscv_options[i].arg != RISCV_OPTION_ARG_NONE) 1122 opts->arg[i] = &args[riscv_options[i].arg]; 1123 else 1124 opts->arg[i] = NULL; 1125 } 1126 /* The array we return must be NULL terminated. */ 1127 opts->name[i] = NULL; 1128 opts->description[i] = NULL; 1129 opts->arg[i] = NULL; 1130 } 1131 1132 return opts_and_args; 1133} 1134 1135void 1136print_riscv_disassembler_options (FILE *stream) 1137{ 1138 const disasm_options_and_args_t *opts_and_args; 1139 const disasm_option_arg_t *args; 1140 const disasm_options_t *opts; 1141 size_t max_len = 0; 1142 size_t i; 1143 size_t j; 1144 1145 opts_and_args = disassembler_options_riscv (); 1146 opts = &opts_and_args->options; 1147 args = opts_and_args->args; 1148 1149 fprintf (stream, _("\n\ 1150The following RISC-V specific disassembler options are supported for use\n\ 1151with the -M switch (multiple options should be separated by commas):\n")); 1152 fprintf (stream, "\n"); 1153 1154 /* Compute the length of the longest option name. */ 1155 for (i = 0; opts->name[i] != NULL; i++) 1156 { 1157 size_t len = strlen (opts->name[i]); 1158 1159 if (opts->arg[i] != NULL) 1160 len += strlen (opts->arg[i]->name); 1161 if (max_len < len) 1162 max_len = len; 1163 } 1164 1165 for (i = 0, max_len++; opts->name[i] != NULL; i++) 1166 { 1167 fprintf (stream, " %s", opts->name[i]); 1168 if (opts->arg[i] != NULL) 1169 fprintf (stream, "%s", opts->arg[i]->name); 1170 if (opts->description[i] != NULL) 1171 { 1172 size_t len = strlen (opts->name[i]); 1173 1174 if (opts->arg != NULL && opts->arg[i] != NULL) 1175 len += strlen (opts->arg[i]->name); 1176 fprintf (stream, "%*c %s", (int) (max_len - len), ' ', 1177 opts->description[i]); 1178 } 1179 fprintf (stream, "\n"); 1180 } 1181 1182 for (i = 0; args[i].name != NULL; i++) 1183 { 1184 fprintf (stream, _("\n\ 1185 For the options above, the following values are supported for \"%s\":\n "), 1186 args[i].name); 1187 for (j = 0; args[i].values[j] != NULL; j++) 1188 fprintf (stream, " %s", args[i].values[j]); 1189 fprintf (stream, _("\n")); 1190 } 1191 1192 fprintf (stream, _("\n")); 1193} 1194