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