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