1 //===-- ABISysV_mips.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ABISysV_mips.h" 10 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/ADT/Triple.h" 13 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/PluginManager.h" 16 #include "lldb/Core/Value.h" 17 #include "lldb/Core/ValueObjectConstResult.h" 18 #include "lldb/Core/ValueObjectMemory.h" 19 #include "lldb/Core/ValueObjectRegister.h" 20 #include "lldb/Symbol/UnwindPlan.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/RegisterContext.h" 23 #include "lldb/Target/StackFrame.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/Thread.h" 26 #include "lldb/Utility/ConstString.h" 27 #include "lldb/Utility/DataExtractor.h" 28 #include "lldb/Utility/Log.h" 29 #include "lldb/Utility/RegisterValue.h" 30 #include "lldb/Utility/Status.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 LLDB_PLUGIN_DEFINE(ABISysV_mips) 36 37 enum dwarf_regnums { 38 dwarf_r0 = 0, 39 dwarf_r1, 40 dwarf_r2, 41 dwarf_r3, 42 dwarf_r4, 43 dwarf_r5, 44 dwarf_r6, 45 dwarf_r7, 46 dwarf_r8, 47 dwarf_r9, 48 dwarf_r10, 49 dwarf_r11, 50 dwarf_r12, 51 dwarf_r13, 52 dwarf_r14, 53 dwarf_r15, 54 dwarf_r16, 55 dwarf_r17, 56 dwarf_r18, 57 dwarf_r19, 58 dwarf_r20, 59 dwarf_r21, 60 dwarf_r22, 61 dwarf_r23, 62 dwarf_r24, 63 dwarf_r25, 64 dwarf_r26, 65 dwarf_r27, 66 dwarf_r28, 67 dwarf_r29, 68 dwarf_r30, 69 dwarf_r31, 70 dwarf_sr, 71 dwarf_lo, 72 dwarf_hi, 73 dwarf_bad, 74 dwarf_cause, 75 dwarf_pc 76 }; 77 78 static const RegisterInfo g_register_infos[] = { 79 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME 80 // DWARF GENERIC PROCESS PLUGINS 81 // LLDB NATIVE VALUE REGS INVALIDATE REGS 82 // ======== ====== == === ============= =========== ============ 83 // ============== ============ ================= 84 // =================== ========== ================= 85 {"r0", 86 "zero", 87 4, 88 0, 89 eEncodingUint, 90 eFormatHex, 91 {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 92 LLDB_INVALID_REGNUM}, 93 nullptr, 94 nullptr, 95 nullptr, 96 0}, 97 {"r1", 98 "AT", 99 4, 100 0, 101 eEncodingUint, 102 eFormatHex, 103 {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 104 LLDB_INVALID_REGNUM}, 105 nullptr, 106 nullptr, 107 nullptr, 108 0}, 109 {"r2", 110 "v0", 111 4, 112 0, 113 eEncodingUint, 114 eFormatHex, 115 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 116 LLDB_INVALID_REGNUM}, 117 nullptr, 118 nullptr, 119 nullptr, 120 0}, 121 {"r3", 122 "v1", 123 4, 124 0, 125 eEncodingUint, 126 eFormatHex, 127 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 128 LLDB_INVALID_REGNUM}, 129 nullptr, 130 nullptr, 131 nullptr, 132 0}, 133 {"r4", 134 "arg1", 135 4, 136 0, 137 eEncodingUint, 138 eFormatHex, 139 {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, 140 LLDB_INVALID_REGNUM}, 141 nullptr, 142 nullptr, 143 nullptr, 144 0}, 145 {"r5", 146 "arg2", 147 4, 148 0, 149 eEncodingUint, 150 eFormatHex, 151 {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, 152 LLDB_INVALID_REGNUM}, 153 nullptr, 154 nullptr, 155 nullptr, 156 0}, 157 {"r6", 158 "arg3", 159 4, 160 0, 161 eEncodingUint, 162 eFormatHex, 163 {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, 164 LLDB_INVALID_REGNUM}, 165 nullptr, 166 nullptr, 167 nullptr, 168 0}, 169 {"r7", 170 "arg4", 171 4, 172 0, 173 eEncodingUint, 174 eFormatHex, 175 {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, 176 LLDB_INVALID_REGNUM}, 177 nullptr, 178 nullptr, 179 nullptr, 180 0}, 181 {"r8", 182 "arg5", 183 4, 184 0, 185 eEncodingUint, 186 eFormatHex, 187 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 188 LLDB_INVALID_REGNUM}, 189 nullptr, 190 nullptr, 191 nullptr, 192 0}, 193 {"r9", 194 "arg6", 195 4, 196 0, 197 eEncodingUint, 198 eFormatHex, 199 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 200 LLDB_INVALID_REGNUM}, 201 nullptr, 202 nullptr, 203 nullptr, 204 0}, 205 {"r10", 206 "arg7", 207 4, 208 0, 209 eEncodingUint, 210 eFormatHex, 211 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 212 LLDB_INVALID_REGNUM}, 213 nullptr, 214 nullptr, 215 nullptr, 216 0}, 217 {"r11", 218 "arg8", 219 4, 220 0, 221 eEncodingUint, 222 eFormatHex, 223 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 224 LLDB_INVALID_REGNUM}, 225 nullptr, 226 nullptr, 227 nullptr, 228 0}, 229 {"r12", 230 nullptr, 231 4, 232 0, 233 eEncodingUint, 234 eFormatHex, 235 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 236 LLDB_INVALID_REGNUM}, 237 nullptr, 238 nullptr, 239 nullptr, 240 0}, 241 {"r13", 242 nullptr, 243 4, 244 0, 245 eEncodingUint, 246 eFormatHex, 247 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 248 LLDB_INVALID_REGNUM}, 249 nullptr, 250 nullptr, 251 nullptr, 252 0}, 253 {"r14", 254 nullptr, 255 4, 256 0, 257 eEncodingUint, 258 eFormatHex, 259 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 260 LLDB_INVALID_REGNUM}, 261 nullptr, 262 nullptr, 263 nullptr, 264 0}, 265 {"r15", 266 nullptr, 267 4, 268 0, 269 eEncodingUint, 270 eFormatHex, 271 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 272 LLDB_INVALID_REGNUM}, 273 nullptr, 274 nullptr, 275 nullptr, 276 0}, 277 {"r16", 278 nullptr, 279 4, 280 0, 281 eEncodingUint, 282 eFormatHex, 283 {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 284 LLDB_INVALID_REGNUM}, 285 nullptr, 286 nullptr, 287 nullptr, 288 0}, 289 {"r17", 290 nullptr, 291 4, 292 0, 293 eEncodingUint, 294 eFormatHex, 295 {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 296 LLDB_INVALID_REGNUM}, 297 nullptr, 298 nullptr, 299 nullptr, 300 0}, 301 {"r18", 302 nullptr, 303 4, 304 0, 305 eEncodingUint, 306 eFormatHex, 307 {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 308 LLDB_INVALID_REGNUM}, 309 nullptr, 310 nullptr, 311 nullptr, 312 0}, 313 {"r19", 314 nullptr, 315 4, 316 0, 317 eEncodingUint, 318 eFormatHex, 319 {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 320 LLDB_INVALID_REGNUM}, 321 nullptr, 322 nullptr, 323 nullptr, 324 0}, 325 {"r20", 326 nullptr, 327 4, 328 0, 329 eEncodingUint, 330 eFormatHex, 331 {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 332 LLDB_INVALID_REGNUM}, 333 nullptr, 334 nullptr, 335 nullptr, 336 0}, 337 {"r21", 338 nullptr, 339 4, 340 0, 341 eEncodingUint, 342 eFormatHex, 343 {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 344 LLDB_INVALID_REGNUM}, 345 nullptr, 346 nullptr, 347 nullptr, 348 0}, 349 {"r22", 350 nullptr, 351 4, 352 0, 353 eEncodingUint, 354 eFormatHex, 355 {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 356 LLDB_INVALID_REGNUM}, 357 nullptr, 358 nullptr, 359 nullptr, 360 0}, 361 {"r23", 362 nullptr, 363 4, 364 0, 365 eEncodingUint, 366 eFormatHex, 367 {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 368 LLDB_INVALID_REGNUM}, 369 nullptr, 370 nullptr, 371 nullptr, 372 0}, 373 {"r24", 374 nullptr, 375 4, 376 0, 377 eEncodingUint, 378 eFormatHex, 379 {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 380 LLDB_INVALID_REGNUM}, 381 nullptr, 382 nullptr, 383 nullptr, 384 0}, 385 {"r25", 386 nullptr, 387 4, 388 0, 389 eEncodingUint, 390 eFormatHex, 391 {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 392 LLDB_INVALID_REGNUM}, 393 nullptr, 394 nullptr, 395 nullptr, 396 0}, 397 {"r26", 398 nullptr, 399 4, 400 0, 401 eEncodingUint, 402 eFormatHex, 403 {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 404 LLDB_INVALID_REGNUM}, 405 nullptr, 406 nullptr, 407 nullptr, 408 0}, 409 {"r27", 410 nullptr, 411 4, 412 0, 413 eEncodingUint, 414 eFormatHex, 415 {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 416 LLDB_INVALID_REGNUM}, 417 nullptr, 418 nullptr, 419 nullptr, 420 0}, 421 {"r28", 422 "gp", 423 4, 424 0, 425 eEncodingUint, 426 eFormatHex, 427 {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 428 LLDB_INVALID_REGNUM}, 429 nullptr, 430 nullptr, 431 nullptr, 432 0}, 433 {"r29", 434 "sp", 435 4, 436 0, 437 eEncodingUint, 438 eFormatHex, 439 {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 440 LLDB_INVALID_REGNUM}, 441 nullptr, 442 nullptr, 443 nullptr, 444 0}, 445 {"r30", 446 "fp", 447 4, 448 0, 449 eEncodingUint, 450 eFormatHex, 451 {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, 452 LLDB_INVALID_REGNUM}, 453 nullptr, 454 nullptr, 455 nullptr, 456 0}, 457 {"r31", 458 "ra", 459 4, 460 0, 461 eEncodingUint, 462 eFormatHex, 463 {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, 464 LLDB_INVALID_REGNUM}, 465 nullptr, 466 nullptr, 467 nullptr, 468 0}, 469 {"sr", 470 nullptr, 471 4, 472 0, 473 eEncodingUint, 474 eFormatHex, 475 {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 476 LLDB_INVALID_REGNUM}, 477 nullptr, 478 nullptr, 479 nullptr, 480 0}, 481 {"lo", 482 nullptr, 483 4, 484 0, 485 eEncodingUint, 486 eFormatHex, 487 {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 488 LLDB_INVALID_REGNUM}, 489 nullptr, 490 nullptr, 491 nullptr, 492 0}, 493 {"hi", 494 nullptr, 495 4, 496 0, 497 eEncodingUint, 498 eFormatHex, 499 {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 500 LLDB_INVALID_REGNUM}, 501 nullptr, 502 nullptr, 503 nullptr, 504 0}, 505 {"bad", 506 nullptr, 507 4, 508 0, 509 eEncodingUint, 510 eFormatHex, 511 {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 512 LLDB_INVALID_REGNUM}, 513 nullptr, 514 nullptr, 515 nullptr, 516 0}, 517 {"cause", 518 nullptr, 519 4, 520 0, 521 eEncodingUint, 522 eFormatHex, 523 {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 524 LLDB_INVALID_REGNUM}, 525 nullptr, 526 nullptr, 527 nullptr, 528 0}, 529 {"pc", 530 nullptr, 531 4, 532 0, 533 eEncodingUint, 534 eFormatHex, 535 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 536 LLDB_INVALID_REGNUM}, 537 nullptr, 538 nullptr, 539 nullptr, 540 0}, 541 }; 542 543 static const uint32_t k_num_register_infos = 544 llvm::array_lengthof(g_register_infos); 545 546 const lldb_private::RegisterInfo * 547 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) { 548 count = k_num_register_infos; 549 return g_register_infos; 550 } 551 552 size_t ABISysV_mips::GetRedZoneSize() const { return 0; } 553 554 // Static Functions 555 556 ABISP 557 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { 558 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); 559 if ((arch_type == llvm::Triple::mips) || 560 (arch_type == llvm::Triple::mipsel)) { 561 return ABISP( 562 new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch))); 563 } 564 return ABISP(); 565 } 566 567 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, 568 addr_t func_addr, addr_t return_addr, 569 llvm::ArrayRef<addr_t> args) const { 570 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 571 572 if (log) { 573 StreamString s; 574 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64 575 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 576 ", return_addr = 0x%" PRIx64, 577 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, 578 (uint64_t)return_addr); 579 580 for (size_t i = 0; i < args.size(); ++i) 581 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]); 582 s.PutCString(")"); 583 log->PutString(s.GetString()); 584 } 585 586 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 587 if (!reg_ctx) 588 return false; 589 590 const RegisterInfo *reg_info = nullptr; 591 592 RegisterValue reg_value; 593 594 // Argument registers 595 const char *reg_names[] = {"r4", "r5", "r6", "r7"}; 596 597 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end(); 598 599 // Write arguments to registers 600 for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) { 601 if (ai == ae) 602 break; 603 604 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 605 LLDB_REGNUM_GENERIC_ARG1 + i); 606 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, 607 args[i], reg_info->name); 608 609 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) 610 return false; 611 612 ++ai; 613 } 614 615 // If we have more than 4 arguments --Spill onto the stack 616 if (ai != ae) { 617 // No of arguments to go on stack 618 size_t num_stack_regs = args.size(); 619 620 // Allocate needed space for args on the stack 621 sp -= (num_stack_regs * 4); 622 623 // Keep the stack 8 byte aligned 624 sp &= ~(8ull - 1ull); 625 626 // just using arg1 to get the right size 627 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( 628 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); 629 630 addr_t arg_pos = sp + 16; 631 632 size_t i = 4; 633 for (; ai != ae; ++ai) { 634 reg_value.SetUInt32(*ai); 635 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "", 636 i + 1, args[i], arg_pos); 637 638 if (reg_ctx 639 ->WriteRegisterValueToMemory(reg_info, arg_pos, 640 reg_info->byte_size, reg_value) 641 .Fail()) 642 return false; 643 arg_pos += reg_info->byte_size; 644 i++; 645 } 646 } 647 648 Status error; 649 const RegisterInfo *pc_reg_info = 650 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 651 const RegisterInfo *sp_reg_info = 652 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 653 const RegisterInfo *ra_reg_info = 654 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); 655 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); 656 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); 657 658 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0); 659 660 /* Write r0 with 0, in case we are stopped in syscall, 661 * such setting prevents automatic decrement of the PC. 662 * This clears the bug 23659 for MIPS. 663 */ 664 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0)) 665 return false; 666 667 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); 668 669 // Set "sp" to the requested value 670 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) 671 return false; 672 673 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); 674 675 // Set "ra" to the return address 676 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) 677 return false; 678 679 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); 680 681 // Set pc to the address of the called function. 682 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) 683 return false; 684 685 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr); 686 687 // All callers of position independent functions must place the address of 688 // the called function in t9 (r25) 689 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr)) 690 return false; 691 692 return true; 693 } 694 695 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const { 696 return false; 697 } 698 699 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, 700 lldb::ValueObjectSP &new_value_sp) { 701 Status error; 702 if (!new_value_sp) { 703 error.SetErrorString("Empty value object for return value."); 704 return error; 705 } 706 707 CompilerType compiler_type = new_value_sp->GetCompilerType(); 708 if (!compiler_type) { 709 error.SetErrorString("Null clang type for return value."); 710 return error; 711 } 712 713 Thread *thread = frame_sp->GetThread().get(); 714 715 bool is_signed; 716 uint32_t count; 717 bool is_complex; 718 719 RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 720 721 bool set_it_simple = false; 722 if (compiler_type.IsIntegerOrEnumerationType(is_signed) || 723 compiler_type.IsPointerType()) { 724 DataExtractor data; 725 Status data_error; 726 size_t num_bytes = new_value_sp->GetData(data, data_error); 727 if (data_error.Fail()) { 728 error.SetErrorStringWithFormat( 729 "Couldn't convert return value to raw data: %s", 730 data_error.AsCString()); 731 return error; 732 } 733 734 lldb::offset_t offset = 0; 735 if (num_bytes <= 8) { 736 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); 737 if (num_bytes <= 4) { 738 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); 739 740 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) 741 set_it_simple = true; 742 } else { 743 uint32_t raw_value = data.GetMaxU32(&offset, 4); 744 745 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) { 746 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); 747 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); 748 749 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value)) 750 set_it_simple = true; 751 } 752 } 753 } else { 754 error.SetErrorString("We don't support returning longer than 64 bit " 755 "integer values at present."); 756 } 757 } else if (compiler_type.IsFloatingPointType(count, is_complex)) { 758 if (is_complex) 759 error.SetErrorString( 760 "We don't support returning complex values at present"); 761 else 762 error.SetErrorString( 763 "We don't support returning float values at present"); 764 } 765 766 if (!set_it_simple) 767 error.SetErrorString( 768 "We only support setting simple integer return types at present."); 769 770 return error; 771 } 772 773 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple( 774 Thread &thread, CompilerType &return_compiler_type) const { 775 ValueObjectSP return_valobj_sp; 776 return return_valobj_sp; 777 } 778 779 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl( 780 Thread &thread, CompilerType &return_compiler_type) const { 781 ValueObjectSP return_valobj_sp; 782 Value value; 783 784 if (!return_compiler_type) 785 return return_valobj_sp; 786 787 ExecutionContext exe_ctx(thread.shared_from_this()); 788 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr) 789 return return_valobj_sp; 790 791 Target *target = exe_ctx.GetTargetPtr(); 792 const ArchSpec target_arch = target->GetArchitecture(); 793 ByteOrder target_byte_order = target_arch.GetByteOrder(); 794 value.SetCompilerType(return_compiler_type); 795 uint32_t fp_flag = 796 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask; 797 798 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 799 if (!reg_ctx) 800 return return_valobj_sp; 801 802 bool is_signed = false; 803 bool is_complex = false; 804 uint32_t count = 0; 805 806 // In MIPS register "r2" (v0) holds the integer function return values 807 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); 808 llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); 809 if (!bit_width) 810 return return_valobj_sp; 811 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) { 812 switch (*bit_width) { 813 default: 814 return return_valobj_sp; 815 case 64: { 816 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); 817 uint64_t raw_value; 818 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX; 819 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) & 820 UINT32_MAX)) 821 << 32; 822 if (is_signed) 823 value.GetScalar() = (int64_t)raw_value; 824 else 825 value.GetScalar() = (uint64_t)raw_value; 826 } break; 827 case 32: 828 if (is_signed) 829 value.GetScalar() = (int32_t)( 830 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX); 831 else 832 value.GetScalar() = (uint32_t)( 833 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX); 834 break; 835 case 16: 836 if (is_signed) 837 value.GetScalar() = (int16_t)( 838 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX); 839 else 840 value.GetScalar() = (uint16_t)( 841 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX); 842 break; 843 case 8: 844 if (is_signed) 845 value.GetScalar() = (int8_t)( 846 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX); 847 else 848 value.GetScalar() = (uint8_t)( 849 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX); 850 break; 851 } 852 } else if (return_compiler_type.IsPointerType()) { 853 uint32_t ptr = 854 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & 855 UINT32_MAX; 856 value.GetScalar() = ptr; 857 } else if (return_compiler_type.IsAggregateType()) { 858 // Structure/Vector is always passed in memory and pointer to that memory 859 // is passed in r2. 860 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned( 861 reg_ctx->GetRegisterInfoByName("r2", 0), 0); 862 // We have got the address. Create a memory object out of it 863 return_valobj_sp = ValueObjectMemory::Create( 864 &thread, "", Address(mem_address, nullptr), return_compiler_type); 865 return return_valobj_sp; 866 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) { 867 if (IsSoftFloat(fp_flag)) { 868 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0); 869 if (count != 1 && is_complex) 870 return return_valobj_sp; 871 switch (*bit_width) { 872 default: 873 return return_valobj_sp; 874 case 32: 875 static_assert(sizeof(float) == sizeof(uint32_t), ""); 876 value.GetScalar() = *((float *)(&raw_value)); 877 break; 878 case 64: 879 static_assert(sizeof(double) == sizeof(uint64_t), ""); 880 const RegisterInfo *r3_reg_info = 881 reg_ctx->GetRegisterInfoByName("r3", 0); 882 if (target_byte_order == eByteOrderLittle) 883 raw_value = 884 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) | 885 raw_value; 886 else 887 raw_value = (raw_value << 32) | 888 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0); 889 value.GetScalar() = *((double *)(&raw_value)); 890 break; 891 } 892 } 893 894 else { 895 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); 896 RegisterValue f0_value; 897 DataExtractor f0_data; 898 reg_ctx->ReadRegister(f0_info, f0_value); 899 f0_value.GetData(f0_data); 900 lldb::offset_t offset = 0; 901 902 if (count == 1 && !is_complex) { 903 switch (*bit_width) { 904 default: 905 return return_valobj_sp; 906 case 64: { 907 static_assert(sizeof(double) == sizeof(uint64_t), ""); 908 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); 909 RegisterValue f1_value; 910 DataExtractor f1_data; 911 reg_ctx->ReadRegister(f1_info, f1_value); 912 DataExtractor *copy_from_extractor = nullptr; 913 DataBufferSP data_sp(new DataBufferHeap(8, 0)); 914 DataExtractor return_ext( 915 data_sp, target_byte_order, 916 target->GetArchitecture().GetAddressByteSize()); 917 918 if (target_byte_order == eByteOrderLittle) { 919 copy_from_extractor = &f0_data; 920 copy_from_extractor->CopyByteOrderedData( 921 offset, 4, data_sp->GetBytes(), 4, target_byte_order); 922 f1_value.GetData(f1_data); 923 copy_from_extractor = &f1_data; 924 copy_from_extractor->CopyByteOrderedData( 925 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order); 926 } else { 927 copy_from_extractor = &f0_data; 928 copy_from_extractor->CopyByteOrderedData( 929 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order); 930 f1_value.GetData(f1_data); 931 copy_from_extractor = &f1_data; 932 copy_from_extractor->CopyByteOrderedData( 933 offset, 4, data_sp->GetBytes(), 4, target_byte_order); 934 } 935 value.GetScalar() = (double)return_ext.GetDouble(&offset); 936 break; 937 } 938 case 32: { 939 static_assert(sizeof(float) == sizeof(uint32_t), ""); 940 value.GetScalar() = (float)f0_data.GetFloat(&offset); 941 break; 942 } 943 } 944 } else { 945 // not handled yet 946 return return_valobj_sp; 947 } 948 } 949 } else { 950 // not handled yet 951 return return_valobj_sp; 952 } 953 954 // If we get here, we have a valid Value, so make our ValueObject out of it: 955 956 return_valobj_sp = ValueObjectConstResult::Create( 957 thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); 958 return return_valobj_sp; 959 } 960 961 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 962 unwind_plan.Clear(); 963 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 964 965 UnwindPlan::RowSP row(new UnwindPlan::Row); 966 967 // Our Call Frame Address is the stack pointer value 968 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); 969 970 // The previous PC is in the RA 971 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); 972 unwind_plan.AppendRow(row); 973 974 // All other registers are the same. 975 976 unwind_plan.SetSourceName("mips at-func-entry default"); 977 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 978 unwind_plan.SetReturnAddressRegister(dwarf_r31); 979 return true; 980 } 981 982 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 983 unwind_plan.Clear(); 984 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 985 986 UnwindPlan::RowSP row(new UnwindPlan::Row); 987 988 row->SetUnspecifiedRegistersAreUndefined(true); 989 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); 990 991 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); 992 993 unwind_plan.AppendRow(row); 994 unwind_plan.SetSourceName("mips default unwind plan"); 995 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 996 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 997 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 998 return true; 999 } 1000 1001 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) { 1002 return !RegisterIsCalleeSaved(reg_info); 1003 } 1004 1005 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const { 1006 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT); 1007 } 1008 1009 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { 1010 if (reg_info) { 1011 // Preserved registers are : 1012 // r16-r23, r28, r29, r30, r31 1013 const char *name = reg_info->name; 1014 1015 if (name[0] == 'r') { 1016 switch (name[1]) { 1017 case '1': 1018 if (name[2] == '6' || name[2] == '7' || name[2] == '8' || 1019 name[2] == '9') // r16-r19 1020 return name[3] == '\0'; 1021 break; 1022 case '2': 1023 if (name[2] == '0' || name[2] == '1' || name[2] == '2' || 1024 name[2] == '3' // r20-r23 1025 || name[2] == '8' || name[2] == '9') // r28 and r29 1026 return name[3] == '\0'; 1027 break; 1028 case '3': 1029 if (name[2] == '0' || name[2] == '1') // r30 and r31 1030 return name[3] == '\0'; 1031 break; 1032 } 1033 1034 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28) 1035 return true; 1036 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29) 1037 return true; 1038 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30) 1039 return true; 1040 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31) 1041 return true; 1042 } 1043 } 1044 return false; 1045 } 1046 1047 void ABISysV_mips::Initialize() { 1048 PluginManager::RegisterPlugin( 1049 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance); 1050 } 1051 1052 void ABISysV_mips::Terminate() { 1053 PluginManager::UnregisterPlugin(CreateInstance); 1054 } 1055 1056 lldb_private::ConstString ABISysV_mips::GetPluginNameStatic() { 1057 static ConstString g_name("sysv-mips"); 1058 return g_name; 1059 } 1060 1061 // PluginInterface protocol 1062 1063 lldb_private::ConstString ABISysV_mips::GetPluginName() { 1064 return GetPluginNameStatic(); 1065 } 1066 1067 uint32_t ABISysV_mips::GetPluginVersion() { return 1; } 1068