brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.0 KiB · e036044 Raw
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