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