brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.1 KiB · c595564 Raw
803 lines · cpp
1//===-- ABIMacOSX_arm64.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 "ABIMacOSX_arm64.h"10 11#include <optional>12#include <vector>13 14#include "llvm/ADT/STLExtras.h"15#include "llvm/TargetParser/Triple.h"16 17#include "lldb/Core/Module.h"18#include "lldb/Core/PluginManager.h"19#include "lldb/Core/Value.h"20#include "lldb/Target/Process.h"21#include "lldb/Target/RegisterContext.h"22#include "lldb/Target/Target.h"23#include "lldb/Target/Thread.h"24#include "lldb/Utility/ConstString.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/Utility/Log.h"27#include "lldb/Utility/RegisterValue.h"28#include "lldb/Utility/Scalar.h"29#include "lldb/Utility/Status.h"30#include "lldb/ValueObject/ValueObjectConstResult.h"31 32using namespace lldb;33using namespace lldb_private;34 35static const char *pluginDesc = "Mac OS X ABI for arm64 targets";36 37size_t ABIMacOSX_arm64::GetRedZoneSize() const { return 128; }38 39// Static Functions40 41ABISP42ABIMacOSX_arm64::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {43  const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();44  const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();45 46  if (vendor_type == llvm::Triple::Apple) {47    if (arch_type == llvm::Triple::aarch64 ||48        arch_type == llvm::Triple::aarch64_32) {49      return ABISP(50          new ABIMacOSX_arm64(std::move(process_sp), MakeMCRegisterInfo(arch)));51    }52  }53 54  return ABISP();55}56 57bool ABIMacOSX_arm64::PrepareTrivialCall(58    Thread &thread, lldb::addr_t sp, lldb::addr_t func_addr,59    lldb::addr_t return_addr, llvm::ArrayRef<lldb::addr_t> args) const {60  RegisterContext *reg_ctx = thread.GetRegisterContext().get();61  if (!reg_ctx)62    return false;63 64  Log *log = GetLog(LLDBLog::Expressions);65 66  if (log) {67    StreamString s;68    s.Printf("ABIMacOSX_arm64::PrepareTrivialCall (tid = 0x%" PRIx6469             ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx6470             ", return_addr = 0x%" PRIx64,71             thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,72             (uint64_t)return_addr);73 74    for (size_t i = 0; i < args.size(); ++i)75      s.Printf(", arg%d = 0x%" PRIx64, static_cast<int>(i + 1), args[i]);76    s.PutCString(")");77    log->PutString(s.GetString());78  }79 80  const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(81      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);82  const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(83      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);84  const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(85      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);86 87  // x0 - x7 contain first 8 simple args88  if (args.size() > 8) // TODO handle more than 8 arguments89    return false;90 91  for (size_t i = 0; i < args.size(); ++i) {92    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(93        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);94    LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s",95              static_cast<int>(i + 1), args[i], reg_info->name);96    if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))97      return false;98  }99 100  // Set "lr" to the return address101  if (!reg_ctx->WriteRegisterFromUnsigned(102          reg_ctx->GetRegisterInfoAtIndex(ra_reg_num), return_addr))103    return false;104 105  // Set "sp" to the requested value106  if (!reg_ctx->WriteRegisterFromUnsigned(107          reg_ctx->GetRegisterInfoAtIndex(sp_reg_num), sp))108    return false;109 110  // Set "pc" to the address requested111  if (!reg_ctx->WriteRegisterFromUnsigned(112          reg_ctx->GetRegisterInfoAtIndex(pc_reg_num), func_addr))113    return false;114 115  return true;116}117 118bool ABIMacOSX_arm64::GetArgumentValues(Thread &thread,119                                        ValueList &values) const {120  uint32_t num_values = values.GetSize();121 122  ExecutionContext exe_ctx(thread.shared_from_this());123 124  // Extract the register context so we can read arguments from registers125 126  RegisterContext *reg_ctx = thread.GetRegisterContext().get();127 128  if (!reg_ctx)129    return false;130 131  addr_t sp = 0;132 133  for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {134    // We currently only support extracting values with Clang QualTypes. Do we135    // care about others?136    Value *value = values.GetValueAtIndex(value_idx);137 138    if (!value)139      return false;140 141    CompilerType value_type = value->GetCompilerType();142    std::optional<uint64_t> bit_size =143        llvm::expectedToOptional(value_type.GetBitSize(&thread));144    if (!bit_size)145      return false;146 147    bool is_signed = false;148    size_t bit_width = 0;149    if (value_type.IsIntegerOrEnumerationType(is_signed)) {150      bit_width = *bit_size;151    } else if (value_type.IsPointerOrReferenceType()) {152      bit_width = *bit_size;153    } else {154      // We only handle integer, pointer and reference types currently...155      return false;156    }157 158    if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) {159      if (value_idx < 8) {160        // Arguments 1-6 are in x0-x5...161        const RegisterInfo *reg_info = nullptr;162        // Search by generic ID first, then fall back to by name163        uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(164            eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);165        if (arg_reg_num != LLDB_INVALID_REGNUM) {166          reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num);167        } else {168          switch (value_idx) {169          case 0:170            reg_info = reg_ctx->GetRegisterInfoByName("x0");171            break;172          case 1:173            reg_info = reg_ctx->GetRegisterInfoByName("x1");174            break;175          case 2:176            reg_info = reg_ctx->GetRegisterInfoByName("x2");177            break;178          case 3:179            reg_info = reg_ctx->GetRegisterInfoByName("x3");180            break;181          case 4:182            reg_info = reg_ctx->GetRegisterInfoByName("x4");183            break;184          case 5:185            reg_info = reg_ctx->GetRegisterInfoByName("x5");186            break;187          case 6:188            reg_info = reg_ctx->GetRegisterInfoByName("x6");189            break;190          case 7:191            reg_info = reg_ctx->GetRegisterInfoByName("x7");192            break;193          }194        }195 196        if (reg_info) {197          RegisterValue reg_value;198 199          if (reg_ctx->ReadRegister(reg_info, reg_value)) {200            if (is_signed)201              reg_value.SignExtend(bit_width);202            if (!reg_value.GetScalarValue(value->GetScalar()))203              return false;204            continue;205          }206        }207        return false;208      } else {209        if (sp == 0) {210          // Read the stack pointer if we already haven't read it211          sp = reg_ctx->GetSP(0);212          if (sp == 0)213            return false;214        }215 216        // Arguments 5 on up are on the stack217        const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8;218        Status error;219        if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(220                sp, arg_byte_size, is_signed, value->GetScalar(), error))221          return false;222 223        sp += arg_byte_size;224        // Align up to the next 8 byte boundary if needed225        if (sp % 8) {226          sp >>= 3;227          sp += 1;228          sp <<= 3;229        }230      }231    }232  }233  return true;234}235 236Status237ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,238                                      lldb::ValueObjectSP &new_value_sp) {239  Status error;240  if (!new_value_sp) {241    error = Status::FromErrorString("Empty value object for return value.");242    return error;243  }244 245  CompilerType return_value_type = new_value_sp->GetCompilerType();246  if (!return_value_type) {247    error = Status::FromErrorString("Null clang type for return value.");248    return error;249  }250 251  Thread *thread = frame_sp->GetThread().get();252 253  RegisterContext *reg_ctx = thread->GetRegisterContext().get();254 255  if (reg_ctx) {256    DataExtractor data;257    Status data_error;258    const uint64_t byte_size = new_value_sp->GetData(data, data_error);259    if (data_error.Fail()) {260      error = Status::FromErrorStringWithFormat(261          "Couldn't convert return value to raw data: %s",262          data_error.AsCString());263      return error;264    }265 266    const uint32_t type_flags = return_value_type.GetTypeInfo(nullptr);267    if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {268      if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {269        // Extract the register context so we can read arguments from registers270        lldb::offset_t offset = 0;271        if (byte_size <= 16) {272          const RegisterInfo *x0_info = reg_ctx->GetRegisterInfoByName("x0", 0);273          if (byte_size <= 8) {274            uint64_t raw_value = data.GetMaxU64(&offset, byte_size);275 276            if (!reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value))277              error = Status::FromErrorString("failed to write register x0");278          } else {279            uint64_t raw_value = data.GetMaxU64(&offset, 8);280 281            if (reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value)) {282              const RegisterInfo *x1_info =283                  reg_ctx->GetRegisterInfoByName("x1", 0);284              raw_value = data.GetMaxU64(&offset, byte_size - offset);285 286              if (!reg_ctx->WriteRegisterFromUnsigned(x1_info, raw_value))287                error = Status::FromErrorString("failed to write register x1");288            }289          }290        } else {291          error = Status::FromErrorString(292              "We don't support returning longer than 128 bit "293              "integer values at present.");294        }295      } else if (type_flags & eTypeIsFloat) {296        if (type_flags & eTypeIsComplex) {297          // Don't handle complex yet.298          error = Status::FromErrorString(299              "returning complex float values are not supported");300        } else {301          const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);302 303          if (v0_info) {304            if (byte_size <= 16) {305              RegisterValue reg_value;306              error = reg_value.SetValueFromData(*v0_info, data, 0, true);307              if (error.Success())308                if (!reg_ctx->WriteRegister(v0_info, reg_value))309                  error =310                      Status::FromErrorString("failed to write register v0");311            } else {312              error = Status::FromErrorString(313                  "returning float values longer than 128 "314                  "bits are not supported");315            }316          } else317            error = Status::FromErrorString(318                "v0 register is not available on this target");319        }320      }321    } else if (type_flags & eTypeIsVector) {322      if (byte_size > 0) {323        const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);324 325        if (v0_info) {326          if (byte_size <= v0_info->byte_size) {327            RegisterValue reg_value;328            error = reg_value.SetValueFromData(*v0_info, data, 0, true);329            if (error.Success()) {330              if (!reg_ctx->WriteRegister(v0_info, reg_value))331                error = Status::FromErrorString("failed to write register v0");332            }333          }334        }335      }336    }337  } else {338    error = Status::FromErrorString("no registers are available");339  }340 341  return error;342}343 344// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says345// registers x19 through x28 and sp are callee preserved. v8-v15 are non-346// volatile (and specifically only the lower 8 bytes of these regs), the rest347// of the fp/SIMD registers are volatile.348//349// v. https://github.com/ARM-software/abi-aa/blob/main/aapcs64/350 351// We treat x29 as callee preserved also, else the unwinder won't try to352// retrieve fp saves.353 354bool ABIMacOSX_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) {355  if (reg_info) {356    const char *name = reg_info->name;357 358    // Sometimes we'll be called with the "alternate" name for these registers;359    // recognize them as non-volatile.360 361    if (name[0] == 'p' && name[1] == 'c') // pc362      return false;363    if (name[0] == 'f' && name[1] == 'p') // fp364      return false;365    if (name[0] == 's' && name[1] == 'p') // sp366      return false;367    if (name[0] == 'l' && name[1] == 'r') // lr368      return false;369 370    if (name[0] == 'x') {371      // Volatile registers: x0-x18, x30 (lr)372      // Return false for the non-volatile gpr regs, true for everything else373      switch (name[1]) {374      case '1':375        switch (name[2]) {376        case '9':377          return false; // x19 is non-volatile378        default:379          return true;380        }381        break;382      case '2':383        switch (name[2]) {384        case '0':385        case '1':386        case '2':387        case '3':388        case '4':389        case '5':390        case '6':391        case '7':392        case '8':393          return false; // x20 - 28 are non-volatile394        case '9':395          return false; // x29 aka fp treat as non-volatile on Darwin396        default:397          return true;398        }399      case '3': // x30 aka lr treat as non-volatile400        if (name[2] == '0')401          return false;402        break;403      default:404        return true;405      }406    } else if (name[0] == 'v' || name[0] == 's' || name[0] == 'd') {407      // Volatile registers: v0-7, v16-v31408      // Return false for non-volatile fp/SIMD regs, true for everything else409      switch (name[1]) {410      case '8':411      case '9':412        return false; // v8-v9 are non-volatile413      case '1':414        switch (name[2]) {415        case '0':416        case '1':417        case '2':418        case '3':419        case '4':420        case '5':421          return false; // v10-v15 are non-volatile422        default:423          return true;424        }425      default:426        return true;427      }428    }429  }430  return true;431}432 433static bool LoadValueFromConsecutiveGPRRegisters(434    ExecutionContext &exe_ctx, RegisterContext *reg_ctx,435    const CompilerType &value_type,436    bool is_return_value, // false => parameter, true => return value437    uint32_t &NGRN,       // NGRN (see ABI documentation)438    uint32_t &NSRN,       // NSRN (see ABI documentation)439    DataExtractor &data) {440  std::optional<uint64_t> byte_size = llvm::expectedToOptional(441      value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));442  if (!byte_size || *byte_size == 0)443    return false;444 445  std::unique_ptr<DataBufferHeap> heap_data_up(446      new DataBufferHeap(*byte_size, 0));447  const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();448  Status error;449 450  CompilerType base_type;451  const uint32_t homogeneous_count =452      value_type.IsHomogeneousAggregate(&base_type);453  if (homogeneous_count > 0 && homogeneous_count <= 8) {454    // Make sure we have enough registers455    if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) {456      if (!base_type)457        return false;458      std::optional<uint64_t> base_byte_size = llvm::expectedToOptional(459          base_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));460      if (!base_byte_size)461        return false;462      uint32_t data_offset = 0;463 464      for (uint32_t i = 0; i < homogeneous_count; ++i) {465        char v_name[8];466        ::snprintf(v_name, sizeof(v_name), "v%u", NSRN);467        const RegisterInfo *reg_info =468            reg_ctx->GetRegisterInfoByName(v_name, 0);469        if (reg_info == nullptr)470          return false;471 472        if (*base_byte_size > reg_info->byte_size)473          return false;474 475        RegisterValue reg_value;476 477        if (!reg_ctx->ReadRegister(reg_info, reg_value))478          return false;479 480        // Make sure we have enough room in "heap_data_up"481        if ((data_offset + *base_byte_size) <= heap_data_up->GetByteSize()) {482          const size_t bytes_copied = reg_value.GetAsMemoryData(483              *reg_info, heap_data_up->GetBytes() + data_offset,484              *base_byte_size, byte_order, error);485          if (bytes_copied != *base_byte_size)486            return false;487          data_offset += bytes_copied;488          ++NSRN;489        } else490          return false;491      }492      data.SetByteOrder(byte_order);493      data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());494      data.SetData(DataBufferSP(heap_data_up.release()));495      return true;496    }497  }498 499  const size_t max_reg_byte_size = 16;500  if (*byte_size <= max_reg_byte_size) {501    size_t bytes_left = *byte_size;502    uint32_t data_offset = 0;503    while (data_offset < *byte_size) {504      if (NGRN >= 8)505        return false;506 507      uint32_t reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(508          eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);509      if (reg_num == LLDB_INVALID_REGNUM)510        return false;511 512      const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);513      if (reg_info == nullptr)514        return false;515 516      RegisterValue reg_value;517 518      if (!reg_ctx->ReadRegister(reg_info, reg_value))519        return false;520 521      const size_t curr_byte_size = std::min<size_t>(8, bytes_left);522      const size_t bytes_copied = reg_value.GetAsMemoryData(523          *reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size,524          byte_order, error);525      if (bytes_copied == 0)526        return false;527      if (bytes_copied >= bytes_left)528        break;529      data_offset += bytes_copied;530      bytes_left -= bytes_copied;531      ++NGRN;532    }533  } else {534    const RegisterInfo *reg_info = nullptr;535    if (is_return_value) {536      // The Darwin arm64 ABI doesn't write the return location back to x8537      // before returning from the function the way the x86_64 ABI does.  So538      // we can't reconstruct stack based returns on exit from the function:539      return false;540    } else {541      // We are assuming we are stopped at the first instruction in a function542      // and that the ABI is being respected so all parameters appear where543      // they should be (functions with no external linkage can legally violate544      // the ABI).545      if (NGRN >= 8)546        return false;547 548      uint32_t reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(549          eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);550      if (reg_num == LLDB_INVALID_REGNUM)551        return false;552      reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);553      if (reg_info == nullptr)554        return false;555      ++NGRN;556    }557 558    const lldb::addr_t value_addr =559        reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS);560 561    if (value_addr == LLDB_INVALID_ADDRESS)562      return false;563 564    if (exe_ctx.GetProcessRef().ReadMemory(565            value_addr, heap_data_up->GetBytes(), heap_data_up->GetByteSize(),566            error) != heap_data_up->GetByteSize()) {567      return false;568    }569  }570 571  data.SetByteOrder(byte_order);572  data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());573  data.SetData(DataBufferSP(heap_data_up.release()));574  return true;575}576 577ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(578    Thread &thread, CompilerType &return_compiler_type) const {579  ValueObjectSP return_valobj_sp;580  Value value;581 582  ExecutionContext exe_ctx(thread.shared_from_this());583  if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)584    return return_valobj_sp;585 586  // value.SetContext (Value::eContextTypeClangType, return_compiler_type);587  value.SetCompilerType(return_compiler_type);588 589  RegisterContext *reg_ctx = thread.GetRegisterContext().get();590  if (!reg_ctx)591    return return_valobj_sp;592 593  std::optional<uint64_t> byte_size =594      llvm::expectedToOptional(return_compiler_type.GetByteSize(&thread));595  if (!byte_size)596    return return_valobj_sp;597 598  const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);599  if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {600    value.SetValueType(Value::ValueType::Scalar);601 602    bool success = false;603    if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {604      // Extract the register context so we can read arguments from registers605      if (*byte_size <= 8) {606        const RegisterInfo *x0_reg_info =607            reg_ctx->GetRegisterInfoByName("x0", 0);608        if (x0_reg_info) {609          uint64_t raw_value =610              thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info,611                                                                  0);612          const bool is_signed = (type_flags & eTypeIsSigned) != 0;613          switch (*byte_size) {614          default:615            break;616          case 16: // uint128_t617            // In register x0 and x1618            {619              const RegisterInfo *x1_reg_info =620                  reg_ctx->GetRegisterInfoByName("x1", 0);621 622              if (x1_reg_info) {623                if (*byte_size <=624                    x0_reg_info->byte_size + x1_reg_info->byte_size) {625                  std::unique_ptr<DataBufferHeap> heap_data_up(626                      new DataBufferHeap(*byte_size, 0));627                  const ByteOrder byte_order =628                      exe_ctx.GetProcessRef().GetByteOrder();629                  RegisterValue x0_reg_value;630                  RegisterValue x1_reg_value;631                  if (reg_ctx->ReadRegister(x0_reg_info, x0_reg_value) &&632                      reg_ctx->ReadRegister(x1_reg_info, x1_reg_value)) {633                    Status error;634                    if (x0_reg_value.GetAsMemoryData(635                            *x0_reg_info, heap_data_up->GetBytes() + 0, 8,636                            byte_order, error) &&637                        x1_reg_value.GetAsMemoryData(638                            *x1_reg_info, heap_data_up->GetBytes() + 8, 8,639                            byte_order, error)) {640                      DataExtractor data(641                          DataBufferSP(heap_data_up.release()), byte_order,642                          exe_ctx.GetProcessRef().GetAddressByteSize());643 644                      return_valobj_sp = ValueObjectConstResult::Create(645                          &thread, return_compiler_type, ConstString(""), data);646                      return return_valobj_sp;647                    }648                  }649                }650              }651            }652            break;653          case sizeof(uint64_t):654            if (is_signed)655              value.GetScalar() = (int64_t)(raw_value);656            else657              value.GetScalar() = (uint64_t)(raw_value);658            success = true;659            break;660 661          case sizeof(uint32_t):662            if (is_signed)663              value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);664            else665              value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);666            success = true;667            break;668 669          case sizeof(uint16_t):670            if (is_signed)671              value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);672            else673              value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);674            success = true;675            break;676 677          case sizeof(uint8_t):678            if (is_signed)679              value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);680            else681              value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);682            success = true;683            break;684          }685        }686      }687    } else if (type_flags & eTypeIsFloat) {688      if (type_flags & eTypeIsComplex) {689        // Don't handle complex yet.690      } else {691        if (*byte_size <= sizeof(long double)) {692          const RegisterInfo *v0_reg_info =693              reg_ctx->GetRegisterInfoByName("v0", 0);694          RegisterValue v0_value;695          if (reg_ctx->ReadRegister(v0_reg_info, v0_value)) {696            DataExtractor data;697            if (v0_value.GetData(data)) {698              lldb::offset_t offset = 0;699              if (*byte_size == sizeof(float)) {700                value.GetScalar() = data.GetFloat(&offset);701                success = true;702              } else if (*byte_size == sizeof(double)) {703                value.GetScalar() = data.GetDouble(&offset);704                success = true;705              } else if (*byte_size == sizeof(long double)) {706                value.GetScalar() = data.GetLongDouble(&offset);707                success = true;708              }709            }710          }711        }712      }713    }714 715    if (success)716      return_valobj_sp = ValueObjectConstResult::Create(717          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));718  } else if (type_flags & eTypeIsVector) {719    if (*byte_size > 0) {720 721      const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);722 723      if (v0_info) {724        if (*byte_size <= v0_info->byte_size) {725          std::unique_ptr<DataBufferHeap> heap_data_up(726              new DataBufferHeap(*byte_size, 0));727          const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();728          RegisterValue reg_value;729          if (reg_ctx->ReadRegister(v0_info, reg_value)) {730            Status error;731            if (reg_value.GetAsMemoryData(*v0_info, heap_data_up->GetBytes(),732                                          heap_data_up->GetByteSize(),733                                          byte_order, error)) {734              DataExtractor data(DataBufferSP(heap_data_up.release()),735                                 byte_order,736                                 exe_ctx.GetProcessRef().GetAddressByteSize());737              return_valobj_sp = ValueObjectConstResult::Create(738                  &thread, return_compiler_type, ConstString(""), data);739            }740          }741        }742      }743    }744  } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) {745    DataExtractor data;746 747    uint32_t NGRN = 0; // Search ABI docs for NGRN748    uint32_t NSRN = 0; // Search ABI docs for NSRN749    const bool is_return_value = true;750    if (LoadValueFromConsecutiveGPRRegisters(751            exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN,752            data)) {753      return_valobj_sp = ValueObjectConstResult::Create(754          &thread, return_compiler_type, ConstString(""), data);755    }756  }757  return return_valobj_sp;758}759 760constexpr addr_t tbi_mask = 0xff80000000000000ULL;761constexpr addr_t pac_sign_extension = 0x0080000000000000ULL;762 763/// Consults the process for its {code, data} address masks and applies it to764/// `addr`.765static addr_t DoFixAddr(addr_t addr, bool is_code, ProcessSP process_sp) {766  if (!process_sp)767    return addr;768 769  addr_t mask = is_code ? process_sp->GetCodeAddressMask()770                        : process_sp->GetDataAddressMask();771  if (mask == LLDB_INVALID_ADDRESS_MASK)772    mask = tbi_mask;773 774  if (addr & pac_sign_extension) {775    addr_t highmem_mask = is_code ? process_sp->GetHighmemCodeAddressMask()776                                  : process_sp->GetHighmemCodeAddressMask();777    if (highmem_mask != LLDB_INVALID_ADDRESS_MASK)778      return addr | highmem_mask;779    return addr | mask;780  }781 782  return addr & (~mask);783}784 785addr_t ABIMacOSX_arm64::FixCodeAddress(addr_t pc) {786  ProcessSP process_sp = GetProcessSP();787  return DoFixAddr(pc, true /*is_code*/, GetProcessSP());788}789 790addr_t ABIMacOSX_arm64::FixDataAddress(addr_t addr) {791  ProcessSP process_sp = GetProcessSP();792  return DoFixAddr(addr, false /*is_code*/, GetProcessSP());793}794 795void ABIMacOSX_arm64::Initialize() {796  PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc,797                                CreateInstance);798}799 800void ABIMacOSX_arm64::Terminate() {801  PluginManager::UnregisterPlugin(CreateInstance);802}803