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