brintos

brintos / llvm-project-archived public Read only

0
0
Text · 33.5 KiB · 6335761 Raw
1079 lines · cpp
1//===-- ABISysV_ppc64.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_ppc64.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/TargetParser/Triple.h"13 14#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"15#include "Utility/PPC64LE_DWARF_Registers.h"16#include "Utility/PPC64_DWARF_Registers.h"17#include "lldb/Core/Module.h"18#include "lldb/Core/PluginManager.h"19#include "lldb/Core/Value.h"20#include "lldb/Symbol/UnwindPlan.h"21#include "lldb/Target/Process.h"22#include "lldb/Target/RegisterContext.h"23#include "lldb/Target/StackFrame.h"24#include "lldb/Target/Target.h"25#include "lldb/Target/Thread.h"26#include "lldb/Utility/ConstString.h"27#include "lldb/Utility/DataExtractor.h"28#include "lldb/Utility/LLDBLog.h"29#include "lldb/Utility/Log.h"30#include "lldb/Utility/RegisterValue.h"31#include "lldb/Utility/Status.h"32#include "lldb/ValueObject/ValueObjectConstResult.h"33#include "lldb/ValueObject/ValueObjectMemory.h"34#include "lldb/ValueObject/ValueObjectRegister.h"35 36#include "clang/AST/ASTContext.h"37#include "clang/AST/Attr.h"38#include "clang/AST/Decl.h"39 40#define DECLARE_REGISTER_INFOS_PPC64_STRUCT41#include "Plugins/Process/Utility/RegisterInfos_ppc64.h"42#undef DECLARE_REGISTER_INFOS_PPC64_STRUCT43 44#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT45#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"46#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT47#include <optional>48 49using namespace lldb;50using namespace lldb_private;51 52LLDB_PLUGIN_DEFINE(ABISysV_ppc64)53 54const lldb_private::RegisterInfo *55ABISysV_ppc64::GetRegisterInfoArray(uint32_t &count) {56  if (GetByteOrder() == lldb::eByteOrderLittle) {57    count = std::size(g_register_infos_ppc64le);58    return g_register_infos_ppc64le;59  } else {60    count = std::size(g_register_infos_ppc64);61    return g_register_infos_ppc64;62  }63}64 65size_t ABISysV_ppc64::GetRedZoneSize() const { return 224; }66 67lldb::ByteOrder ABISysV_ppc64::GetByteOrder() const {68  return GetProcessSP()->GetByteOrder();69}70 71// Static Functions72 73ABISP74ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp,75                              const ArchSpec &arch) {76  if (arch.GetTriple().isPPC64())77    return ABISP(78        new ABISysV_ppc64(std::move(process_sp), MakeMCRegisterInfo(arch)));79  return ABISP();80}81 82bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp,83                                       addr_t func_addr, addr_t return_addr,84                                       llvm::ArrayRef<addr_t> args) const {85  Log *log = GetLog(LLDBLog::Expressions);86 87  if (log) {88    StreamString s;89    s.Printf("ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx6490             ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx6491             ", return_addr = 0x%" PRIx64,92             thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,93             (uint64_t)return_addr);94 95    for (size_t i = 0; i < args.size(); ++i)96      s.Printf(", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1),97               args[i]);98    s.PutCString(")");99    log->PutString(s.GetString());100  }101 102  RegisterContext *reg_ctx = thread.GetRegisterContext().get();103  if (!reg_ctx)104    return false;105 106  const RegisterInfo *reg_info = nullptr;107 108  if (args.size() > 8) // TODO handle more than 8 arguments109    return false;110 111  for (size_t i = 0; i < args.size(); ++i) {112    reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,113                                        LLDB_REGNUM_GENERIC_ARG1 + i);114    LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s",115              static_cast<uint64_t>(i + 1), args[i], reg_info->name);116    if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))117      return false;118  }119 120  // First, align the SP121 122  LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,123            (uint64_t)sp, (uint64_t)(sp & ~0xfull));124 125  sp &= ~(0xfull); // 16-byte alignment126 127  sp -= 544; // allocate frame to save TOC, RA and SP.128 129  Status error;130  uint64_t reg_value;131  const RegisterInfo *pc_reg_info =132      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);133  const RegisterInfo *sp_reg_info =134      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);135  ProcessSP process_sp(thread.GetProcess());136  const RegisterInfo *lr_reg_info =137      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);138  const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoAtIndex(2);139  const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12);140 141  // Save return address onto the stack.142  LLDB_LOGF(log,143            "Pushing the return address onto the stack: 0x%" PRIx64144            "(+16): 0x%" PRIx64,145            (uint64_t)sp, (uint64_t)return_addr);146  if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error))147    return false;148 149  // Write the return address to link register.150  LLDB_LOGF(log, "Writing LR: 0x%" PRIx64, (uint64_t)return_addr);151  if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr))152    return false;153 154  // Write target address to %r12 register.155  LLDB_LOGF(log, "Writing R12: 0x%" PRIx64, (uint64_t)func_addr);156  if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr))157    return false;158 159  // Read TOC pointer value.160  reg_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);161 162  // Write TOC pointer onto the stack.163  uint64_t stack_offset;164  if (GetByteOrder() == lldb::eByteOrderLittle)165    stack_offset = 24;166  else167    stack_offset = 40;168 169  LLDB_LOGF(log, "Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64,170            (uint64_t)(sp + stack_offset), (int)stack_offset,171            (uint64_t)reg_value);172  if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error))173    return false;174 175  // Read the current SP value.176  reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0);177 178  // Save current SP onto the stack.179  LLDB_LOGF(log, "Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp,180            (uint64_t)reg_value);181  if (!process_sp->WritePointerToMemory(sp, reg_value, error))182    return false;183 184  // %r1 is set to the actual stack value.185  LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);186 187  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))188    return false;189 190  // %pc is set to the address of the called function.191 192  LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr);193 194  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))195    return false;196 197  return true;198}199 200static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,201                                bool is_signed, Thread &thread,202                                uint32_t *argument_register_ids,203                                unsigned int &current_argument_register,204                                addr_t &current_stack_argument) {205  if (bit_width > 64)206    return false; // Scalar can't hold large integer arguments207 208  if (current_argument_register < 6) {209    scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(210        argument_register_ids[current_argument_register], 0);211    current_argument_register++;212    if (is_signed)213      scalar.SignExtend(bit_width);214  } else {215    uint32_t byte_size = (bit_width + (8 - 1)) / 8;216    Status error;217    if (thread.GetProcess()->ReadScalarIntegerFromMemory(218            current_stack_argument, byte_size, is_signed, scalar, error)) {219      current_stack_argument += byte_size;220      return true;221    }222    return false;223  }224  return true;225}226 227bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const {228  unsigned int num_values = values.GetSize();229  unsigned int value_index;230 231  // Extract the register context so we can read arguments from registers232 233  RegisterContext *reg_ctx = thread.GetRegisterContext().get();234 235  if (!reg_ctx)236    return false;237 238  // Get the pointer to the first stack argument so we have a place to start239  // when reading data240 241  addr_t sp = reg_ctx->GetSP(0);242 243  if (!sp)244    return false;245 246  uint64_t stack_offset;247  if (GetByteOrder() == lldb::eByteOrderLittle)248    stack_offset = 32;249  else250    stack_offset = 48;251 252  // jump over return address.253  addr_t current_stack_argument = sp + stack_offset;254  uint32_t argument_register_ids[8];255 256  for (size_t i = 0; i < 8; ++i) {257    argument_register_ids[i] =258        reg_ctx259            ->GetRegisterInfo(eRegisterKindGeneric,260                              LLDB_REGNUM_GENERIC_ARG1 + i)261            ->kinds[eRegisterKindLLDB];262  }263 264  unsigned int current_argument_register = 0;265 266  for (value_index = 0; value_index < num_values; ++value_index) {267    Value *value = values.GetValueAtIndex(value_index);268 269    if (!value)270      return false;271 272    // We currently only support extracting values with Clang QualTypes. Do we273    // care about others?274    CompilerType compiler_type = value->GetCompilerType();275    std::optional<uint64_t> bit_size =276        llvm::expectedToOptional(compiler_type.GetBitSize(&thread));277    if (!bit_size)278      return false;279    bool is_signed;280 281    if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {282      ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,283                          argument_register_ids, current_argument_register,284                          current_stack_argument);285    } else if (compiler_type.IsPointerType()) {286      ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,287                          argument_register_ids, current_argument_register,288                          current_stack_argument);289    }290  }291 292  return true;293}294 295Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,296                                           lldb::ValueObjectSP &new_value_sp) {297  Status error;298  if (!new_value_sp) {299    error = Status::FromErrorString("Empty value object for return value.");300    return error;301  }302 303  CompilerType compiler_type = new_value_sp->GetCompilerType();304  if (!compiler_type) {305    error = Status::FromErrorString("Null clang type for return value.");306    return error;307  }308 309  Thread *thread = frame_sp->GetThread().get();310 311  bool is_signed;312  bool is_complex;313 314  RegisterContext *reg_ctx = thread->GetRegisterContext().get();315 316  bool set_it_simple = false;317  if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||318      compiler_type.IsPointerType()) {319    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);320 321    DataExtractor data;322    Status data_error;323    size_t num_bytes = new_value_sp->GetData(data, data_error);324    if (data_error.Fail()) {325      error = Status::FromErrorStringWithFormat(326          "Couldn't convert return value to raw data: %s",327          data_error.AsCString());328      return error;329    }330    lldb::offset_t offset = 0;331    if (num_bytes <= 8) {332      uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);333 334      if (reg_ctx->WriteRegisterFromUnsigned(reg_info, raw_value))335        set_it_simple = true;336    } else {337      error = Status::FromErrorString(338          "We don't support returning longer than 64 bit "339          "integer values at present.");340    }341  } else if (compiler_type.IsFloatingPointType(is_complex)) {342    if (is_complex)343      error = Status::FromErrorString(344          "We don't support returning complex values at present");345    else {346      std::optional<uint64_t> bit_width =347          llvm::expectedToOptional(compiler_type.GetBitSize(frame_sp.get()));348      if (!bit_width) {349        error = Status::FromErrorString("can't get size of type");350        return error;351      }352      if (*bit_width <= 64) {353        DataExtractor data;354        Status data_error;355        size_t num_bytes = new_value_sp->GetData(data, data_error);356        if (data_error.Fail()) {357          error = Status::FromErrorStringWithFormat(358              "Couldn't convert return value to raw data: %s",359              data_error.AsCString());360          return error;361        }362 363        unsigned char buffer[16];364        ByteOrder byte_order = data.GetByteOrder();365 366        data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order);367        set_it_simple = true;368      } else {369        // FIXME - don't know how to do 80 bit long doubles yet.370        error = Status::FromErrorString(371            "We don't support returning float values > 64 bits at present");372      }373    }374  }375 376  if (!set_it_simple) {377    // Okay we've got a structure or something that doesn't fit in a simple378    // register. We should figure out where it really goes, but we don't379    // support this yet.380    error = Status::FromErrorString(381        "We only support setting simple integer and float "382        "return types at present.");383  }384 385  return error;386}387 388//389// ReturnValueExtractor390//391 392namespace {393 394#define LOG_PREFIX "ReturnValueExtractor: "395 396class ReturnValueExtractor {397  // This class represents a register, from which data may be extracted.398  //399  // It may be constructed by directly specifying its index (where 0 is the400  // first register used to return values) or by specifying the offset of a401  // given struct field, in which case the appropriated register index will be402  // calculated.403  class Register {404  public:405    enum Type {406      GPR, // General Purpose Register407      FPR  // Floating Point Register408    };409 410    // main constructor411    //412    // offs - field offset in struct413    Register(Type ty, uint32_t index, uint32_t offs, RegisterContext *reg_ctx,414             ByteOrder byte_order)415        : m_index(index), m_offs(offs % sizeof(uint64_t)),416          m_avail(sizeof(uint64_t) - m_offs), m_type(ty), m_reg_ctx(reg_ctx),417          m_byte_order(byte_order) {}418 419    // explicit index, no offset420    Register(Type ty, uint32_t index, RegisterContext *reg_ctx,421             ByteOrder byte_order)422        : Register(ty, index, 0, reg_ctx, byte_order) {}423 424    // GPR, calculate index from offs425    Register(uint32_t offs, RegisterContext *reg_ctx, ByteOrder byte_order)426        : Register(GPR, offs / sizeof(uint64_t), offs, reg_ctx, byte_order) {}427 428    uint32_t Index() const { return m_index; }429 430    // register offset where data is located431    uint32_t Offs() const { return m_offs; }432 433    // available bytes in this register434    uint32_t Avail() const { return m_avail; }435 436    bool IsValid() const {437      if (m_index > 7) {438        LLDB_LOG(m_log, LOG_PREFIX439                 "No more than 8 registers should be used to return values");440        return false;441      }442      return true;443    }444 445    std::string GetName() const {446      if (m_type == GPR)447        return ("r" + llvm::Twine(m_index + 3)).str();448      else449        return ("f" + llvm::Twine(m_index + 1)).str();450    }451 452    // get raw register data453    bool GetRawData(uint64_t &raw_data) {454      const RegisterInfo *reg_info =455          m_reg_ctx->GetRegisterInfoByName(GetName());456      if (!reg_info) {457        LLDB_LOG(m_log, LOG_PREFIX "Failed to get RegisterInfo");458        return false;459      }460 461      RegisterValue reg_val;462      if (!m_reg_ctx->ReadRegister(reg_info, reg_val)) {463        LLDB_LOG(m_log, LOG_PREFIX "ReadRegister() failed");464        return false;465      }466 467      Status error;468      uint32_t rc = reg_val.GetAsMemoryData(469          *reg_info, &raw_data, sizeof(raw_data), m_byte_order, error);470      if (rc != sizeof(raw_data)) {471        LLDB_LOG(m_log, LOG_PREFIX "GetAsMemoryData() failed");472        return false;473      }474 475      return true;476    }477 478  private:479    uint32_t m_index;480    uint32_t m_offs;481    uint32_t m_avail;482    Type m_type;483    RegisterContext *m_reg_ctx;484    ByteOrder m_byte_order;485    Log *m_log = GetLog(LLDBLog::Expressions);486  };487 488  Register GetGPR(uint32_t index) const {489    return Register(Register::GPR, index, m_reg_ctx, m_byte_order);490  }491 492  Register GetFPR(uint32_t index) const {493    return Register(Register::FPR, index, m_reg_ctx, m_byte_order);494  }495 496  Register GetGPRByOffs(uint32_t offs) const {497    return Register(offs, m_reg_ctx, m_byte_order);498  }499 500public:501  // factory502  static llvm::Expected<ReturnValueExtractor> Create(Thread &thread,503                                                     CompilerType &type) {504    RegisterContext *reg_ctx = thread.GetRegisterContext().get();505    if (!reg_ctx)506      return llvm::createStringError(LOG_PREFIX507                                     "Failed to get RegisterContext");508 509    ProcessSP process_sp = thread.GetProcess();510    if (!process_sp)511      return llvm::createStringError(LOG_PREFIX "GetProcess() failed");512 513    return ReturnValueExtractor(thread, type, reg_ctx, process_sp);514  }515 516  // main method: get value of the type specified at construction time517  ValueObjectSP GetValue() {518    const uint32_t type_flags = m_type.GetTypeInfo();519 520    // call the appropriate type handler521    ValueSP value_sp;522    ValueObjectSP valobj_sp;523    if (type_flags & eTypeIsScalar) {524      if (type_flags & eTypeIsInteger) {525        value_sp = GetIntegerValue(0);526      } else if (type_flags & eTypeIsFloat) {527        if (type_flags & eTypeIsComplex) {528          LLDB_LOG(m_log, LOG_PREFIX "Complex numbers are not supported yet");529          return ValueObjectSP();530        } else {531          value_sp = GetFloatValue(m_type, 0);532        }533      }534    } else if (type_flags & eTypeIsPointer) {535      value_sp = GetPointerValue(0);536    }537 538    if (value_sp) {539      valobj_sp = ValueObjectConstResult::Create(540          m_thread.GetStackFrameAtIndex(0).get(), *value_sp, ConstString(""));541    } else if (type_flags & eTypeIsVector) {542      valobj_sp = GetVectorValueObject();543    } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) {544      valobj_sp = GetStructValueObject();545    }546 547    return valobj_sp;548  }549 550private:551  // data552  Thread &m_thread;553  CompilerType &m_type;554  uint64_t m_byte_size;555  std::unique_ptr<DataBufferHeap> m_data_up;556  int32_t m_src_offs = 0;557  int32_t m_dst_offs = 0;558  bool m_packed = false;559  Log *m_log = GetLog(LLDBLog::Expressions);560  RegisterContext *m_reg_ctx;561  ProcessSP m_process_sp;562  ByteOrder m_byte_order;563  uint32_t m_addr_size;564 565  // methods566 567  // constructor568  ReturnValueExtractor(Thread &thread, CompilerType &type,569                       RegisterContext *reg_ctx, ProcessSP process_sp)570      : m_thread(thread), m_type(type),571        m_byte_size(572            llvm::expectedToOptional(m_type.GetByteSize(&thread)).value_or(0)),573        m_data_up(new DataBufferHeap(m_byte_size, 0)), m_reg_ctx(reg_ctx),574        m_process_sp(process_sp), m_byte_order(process_sp->GetByteOrder()),575        m_addr_size(576            process_sp->GetTarget().GetArchitecture().GetAddressByteSize()) {}577 578  // build a new scalar value579  ValueSP NewScalarValue(CompilerType &type) {580    ValueSP value_sp(new Value);581    value_sp->SetCompilerType(type);582    value_sp->SetValueType(Value::ValueType::Scalar);583    return value_sp;584  }585 586  // get an integer value in the specified register587  ValueSP GetIntegerValue(uint32_t reg_index) {588    uint64_t raw_value;589    auto reg = GetGPR(reg_index);590    if (!reg.GetRawData(raw_value))591      return ValueSP();592 593    // build value from data594    ValueSP value_sp(NewScalarValue(m_type));595 596    uint32_t type_flags = m_type.GetTypeInfo();597    bool is_signed = (type_flags & eTypeIsSigned) != 0;598 599    switch (m_byte_size) {600    case sizeof(uint64_t):601      if (is_signed)602        value_sp->GetScalar() = (int64_t)(raw_value);603      else604        value_sp->GetScalar() = (uint64_t)(raw_value);605      break;606 607    case sizeof(uint32_t):608      if (is_signed)609        value_sp->GetScalar() = (int32_t)(raw_value & UINT32_MAX);610      else611        value_sp->GetScalar() = (uint32_t)(raw_value & UINT32_MAX);612      break;613 614    case sizeof(uint16_t):615      if (is_signed)616        value_sp->GetScalar() = (int16_t)(raw_value & UINT16_MAX);617      else618        value_sp->GetScalar() = (uint16_t)(raw_value & UINT16_MAX);619      break;620 621    case sizeof(uint8_t):622      if (is_signed)623        value_sp->GetScalar() = (int8_t)(raw_value & UINT8_MAX);624      else625        value_sp->GetScalar() = (uint8_t)(raw_value & UINT8_MAX);626      break;627 628    default:629      llvm_unreachable("Invalid integer size");630    }631 632    return value_sp;633  }634 635  // get a floating point value on the specified register636  ValueSP GetFloatValue(CompilerType &type, uint32_t reg_index) {637    uint64_t raw_data;638    auto reg = GetFPR(reg_index);639    if (!reg.GetRawData(raw_data))640      return {};641 642    // build value from data643    ValueSP value_sp(NewScalarValue(type));644 645    DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size);646 647    lldb::offset_t offset = 0;648    std::optional<uint64_t> byte_size =649        llvm::expectedToOptional(type.GetByteSize(m_process_sp.get()));650    if (!byte_size)651      return {};652    switch (*byte_size) {653    case sizeof(float):654      value_sp->GetScalar() = (float)de.GetDouble(&offset);655      break;656 657    case sizeof(double):658      value_sp->GetScalar() = de.GetDouble(&offset);659      break;660 661    default:662      llvm_unreachable("Invalid floating point size");663    }664 665    return value_sp;666  }667 668  // get pointer value from register669  ValueSP GetPointerValue(uint32_t reg_index) {670    uint64_t raw_data;671    auto reg = GetGPR(reg_index);672    if (!reg.GetRawData(raw_data))673      return ValueSP();674 675    // build value from raw data676    ValueSP value_sp(NewScalarValue(m_type));677    value_sp->GetScalar() = raw_data;678    return value_sp;679  }680 681  // build the ValueObject from our data buffer682  ValueObjectSP BuildValueObject() {683    DataExtractor de(DataBufferSP(m_data_up.release()), m_byte_order,684                     m_addr_size);685    return ValueObjectConstResult::Create(&m_thread, m_type, ConstString(""),686                                          de);687  }688 689  // get a vector return value690  ValueObjectSP GetVectorValueObject() {691    const uint32_t MAX_VRS = 2;692 693    // get first V register used to return values694    const RegisterInfo *vr[MAX_VRS];695    vr[0] = m_reg_ctx->GetRegisterInfoByName("vr2");696    if (!vr[0]) {697      LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr2 RegisterInfo");698      return ValueObjectSP();699    }700 701    const uint32_t vr_size = vr[0]->byte_size;702    size_t vrs = 1;703    if (m_byte_size > 2 * vr_size) {704      LLDB_LOG(705          m_log, LOG_PREFIX706          "Returning vectors that don't fit in 2 VR regs is not supported");707      return ValueObjectSP();708    }709 710    // load vr3, if needed711    if (m_byte_size > vr_size) {712      vrs++;713      vr[1] = m_reg_ctx->GetRegisterInfoByName("vr3");714      if (!vr[1]) {715        LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr3 RegisterInfo");716        return ValueObjectSP();717      }718    }719 720    // Get the whole contents of vector registers and let the logic here721    // arrange the data properly.722 723    RegisterValue vr_val[MAX_VRS];724    Status error;725    std::unique_ptr<DataBufferHeap> vr_data(726        new DataBufferHeap(vrs * vr_size, 0));727 728    for (uint32_t i = 0; i < vrs; i++) {729      if (!m_reg_ctx->ReadRegister(vr[i], vr_val[i])) {730        LLDB_LOG(m_log, LOG_PREFIX "Failed to read vector register contents");731        return ValueObjectSP();732      }733      if (!vr_val[i].GetAsMemoryData(*vr[i], vr_data->GetBytes() + i * vr_size,734                                     vr_size, m_byte_order, error)) {735        LLDB_LOG(m_log, LOG_PREFIX "Failed to extract vector register bytes");736        return ValueObjectSP();737      }738    }739 740    // The compiler generated code seems to always put the vector elements at741    // the end of the vector register, in case they don't occupy all of it.742    // This offset variable handles this.743    uint32_t offs = 0;744    if (m_byte_size < vr_size)745      offs = vr_size - m_byte_size;746 747    // copy extracted data to our buffer748    memcpy(m_data_up->GetBytes(), vr_data->GetBytes() + offs, m_byte_size);749    return BuildValueObject();750  }751 752  // get a struct return value753  ValueObjectSP GetStructValueObject() {754    // case 1: get from stack755    if (m_byte_size > 2 * sizeof(uint64_t)) {756      uint64_t addr;757      auto reg = GetGPR(0);758      if (!reg.GetRawData(addr))759        return {};760 761      Status error;762      size_t rc = m_process_sp->ReadMemory(addr, m_data_up->GetBytes(),763                                           m_byte_size, error);764      if (rc != m_byte_size) {765        LLDB_LOG(m_log, LOG_PREFIX "Failed to read memory pointed by r3");766        return ValueObjectSP();767      }768      return BuildValueObject();769    }770 771    // get number of children772    const bool omit_empty_base_classes = true;773    auto n_or_err = m_type.GetNumChildren(omit_empty_base_classes, nullptr);774    if (!n_or_err) {775      LLDB_LOG_ERROR(m_log, n_or_err.takeError(), LOG_PREFIX "{0}");776      return {};777    }778    uint32_t n = *n_or_err;779    if (!n) {780      LLDB_LOG(m_log, LOG_PREFIX "No children found in struct");781      return {};782    }783 784    // case 2: homogeneous double or float aggregate785    CompilerType elem_type;786    if (m_type.IsHomogeneousAggregate(&elem_type)) {787      uint32_t type_flags = elem_type.GetTypeInfo();788      std::optional<uint64_t> elem_size =789          llvm::expectedToOptional(elem_type.GetByteSize(m_process_sp.get()));790      if (!elem_size)791        return {};792      if (type_flags & eTypeIsComplex || !(type_flags & eTypeIsFloat)) {793        LLDB_LOG(m_log,794                 LOG_PREFIX "Unexpected type found in homogeneous aggregate");795        return {};796      }797 798      for (uint32_t i = 0; i < n; i++) {799        ValueSP val_sp = GetFloatValue(elem_type, i);800        if (!val_sp)801          return {};802 803        // copy to buffer804        Status error;805        size_t rc = val_sp->GetScalar().GetAsMemoryData(806            m_data_up->GetBytes() + m_dst_offs, *elem_size, m_byte_order,807            error);808        if (rc != *elem_size) {809          LLDB_LOG(m_log, LOG_PREFIX "Failed to get float data");810          return {};811        }812        m_dst_offs += *elem_size;813      }814      return BuildValueObject();815    }816 817    // case 3: get from GPRs818 819    // first, check if this is a packed struct or not820    auto ast = m_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();821    if (ast) {822      clang::RecordDecl *record_decl = TypeSystemClang::GetAsRecordDecl(m_type);823 824      if (record_decl) {825        auto attrs = record_decl->attrs();826        for (const auto &attr : attrs) {827          if (attr->getKind() == clang::attr::Packed) {828            m_packed = true;829            break;830          }831        }832      }833    }834 835    LLDB_LOG(m_log, LOG_PREFIX "{0} struct",836             m_packed ? "packed" : "not packed");837 838    for (uint32_t i = 0; i < n; i++) {839      std::string name;840      uint32_t size;841      (void)GetChildType(i, name, size);842      // NOTE: the offset returned by GetChildCompilerTypeAtIndex()843      //       can't be used because it never considers alignment bytes844      //       between struct fields.845      LLDB_LOG(m_log, LOG_PREFIX "field={0}, size={1}", name, size);846      if (!ExtractField(size))847        return ValueObjectSP();848    }849 850    return BuildValueObject();851  }852 853  // extract 'size' bytes at 'offs' from GPRs854  bool ExtractFromRegs(int32_t offs, uint32_t size, void *buf) {855    while (size) {856      auto reg = GetGPRByOffs(offs);857      if (!reg.IsValid())858        return false;859 860      uint32_t n = std::min(reg.Avail(), size);861      uint64_t raw_data;862 863      if (!reg.GetRawData(raw_data))864        return false;865 866      memcpy(buf, (char *)&raw_data + reg.Offs(), n);867      offs += n;868      size -= n;869      buf = (char *)buf + n;870    }871    return true;872  }873 874  // extract one field from GPRs and put it in our buffer875  bool ExtractField(uint32_t size) {876    auto reg = GetGPRByOffs(m_src_offs);877    if (!reg.IsValid())878      return false;879 880    // handle padding881    if (!m_packed) {882      uint32_t n = m_src_offs % size;883 884      // not 'size' bytes aligned885      if (n) {886        LLDB_LOG(m_log,887                 LOG_PREFIX "Extracting {0} alignment bytes at offset {1}", n,888                 m_src_offs);889        // get alignment bytes890        if (!ExtractFromRegs(m_src_offs, n, m_data_up->GetBytes() + m_dst_offs))891          return false;892        m_src_offs += n;893        m_dst_offs += n;894      }895    }896 897    // get field898    LLDB_LOG(m_log, LOG_PREFIX "Extracting {0} field bytes at offset {1}", size,899             m_src_offs);900    if (!ExtractFromRegs(m_src_offs, size, m_data_up->GetBytes() + m_dst_offs))901      return false;902    m_src_offs += size;903    m_dst_offs += size;904    return true;905  }906 907  // get child908  llvm::Expected<CompilerType> GetChildType(uint32_t i, std::string &name,909                                            uint32_t &size) {910    // GetChild constant inputs911    const bool transparent_pointers = false;912    const bool omit_empty_base_classes = true;913    const bool ignore_array_bounds = false;914    // GetChild output params915    int32_t child_offs;916    uint32_t child_bitfield_bit_size;917    uint32_t child_bitfield_bit_offset;918    bool child_is_base_class;919    bool child_is_deref_of_parent;920    ValueObject *valobj = nullptr;921    uint64_t language_flags;922    ExecutionContext exe_ctx;923    m_thread.CalculateExecutionContext(exe_ctx);924 925    return m_type.GetChildCompilerTypeAtIndex(926        &exe_ctx, i, transparent_pointers, omit_empty_base_classes,927        ignore_array_bounds, name, size, child_offs, child_bitfield_bit_size,928        child_bitfield_bit_offset, child_is_base_class,929        child_is_deref_of_parent, valobj, language_flags);930  }931};932 933#undef LOG_PREFIX934 935} // anonymous namespace936 937ValueObjectSP938ABISysV_ppc64::GetReturnValueObjectSimple(Thread &thread,939                                          CompilerType &type) const {940  if (!type)941    return ValueObjectSP();942 943  auto exp_extractor = ReturnValueExtractor::Create(thread, type);944  if (!exp_extractor) {945    Log *log = GetLog(LLDBLog::Expressions);946    LLDB_LOG_ERROR(log, exp_extractor.takeError(),947                   "Extracting return value failed: {0}");948    return ValueObjectSP();949  }950 951  return exp_extractor.get().GetValue();952}953 954ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl(955    Thread &thread, CompilerType &return_compiler_type) const {956  return GetReturnValueObjectSimple(thread, return_compiler_type);957}958 959UnwindPlanSP ABISysV_ppc64::CreateFunctionEntryUnwindPlan() {960 961  uint32_t lr_reg_num;962  uint32_t sp_reg_num;963  uint32_t pc_reg_num;964 965  if (GetByteOrder() == lldb::eByteOrderLittle) {966    lr_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le;967    sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le;968    pc_reg_num = ppc64le_dwarf::dwarf_pc_ppc64le;969  } else {970    lr_reg_num = ppc64_dwarf::dwarf_lr_ppc64;971    sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64;972    pc_reg_num = ppc64_dwarf::dwarf_pc_ppc64;973  }974 975  UnwindPlan::Row row;976 977  // Our Call Frame Address is the stack pointer value978  row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);979 980  // The previous PC is in the LR. All other registers are the same.981  row.SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);982 983  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);984  plan_sp->AppendRow(std::move(row));985  plan_sp->SetSourceName("ppc64 at-func-entry default");986  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);987  return plan_sp;988}989 990UnwindPlanSP ABISysV_ppc64::CreateDefaultUnwindPlan() {991  uint32_t sp_reg_num;992  uint32_t pc_reg_num;993  uint32_t cr_reg_num;994 995  if (GetByteOrder() == lldb::eByteOrderLittle) {996    sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le;997    pc_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le;998    cr_reg_num = ppc64le_dwarf::dwarf_cr_ppc64le;999  } else {1000    sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64;1001    pc_reg_num = ppc64_dwarf::dwarf_lr_ppc64;1002    cr_reg_num = ppc64_dwarf::dwarf_cr_ppc64;1003  }1004 1005  UnwindPlan::Row row;1006  const int32_t ptr_size = 8;1007  row.SetUnspecifiedRegistersAreUndefined(true);1008  row.GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);1009 1010  row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);1011  row.SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);1012  row.SetRegisterLocationToAtCFAPlusOffset(cr_reg_num, ptr_size, true);1013 1014  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);1015  plan_sp->AppendRow(std::move(row));1016  plan_sp->SetSourceName("ppc64 default unwind plan");1017  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);1018  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);1019  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);1020  plan_sp->SetReturnAddressRegister(pc_reg_num);1021  return plan_sp;1022}1023 1024bool ABISysV_ppc64::RegisterIsVolatile(const RegisterInfo *reg_info) {1025  return !RegisterIsCalleeSaved(reg_info);1026}1027 1028// See "Register Usage" in the1029// "System V Application Binary Interface"1030// "64-bit PowerPC ELF Application Binary Interface Supplement" current version1031// is 2 released 2015 at1032// https://members.openpowerfoundation.org/document/dl/5761033bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {1034  if (reg_info) {1035    // Preserved registers are :1036    //    r1,r2,r13-r311037    //    cr2-cr4 (partially preserved)1038    //    f14-f31 (not yet)1039    //    v20-v31 (not yet)1040    //    vrsave (not yet)1041 1042    const char *name = reg_info->name;1043    if (name[0] == 'r') {1044      if ((name[1] == '1' || name[1] == '2') && name[2] == '\0')1045        return true;1046      if (name[1] == '1' && name[2] > '2')1047        return true;1048      if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')1049        return true;1050    }1051 1052    if (name[0] == 'f' && name[1] >= '0' && name[2] <= '9') {1053      if (name[2] == '\0')1054        return false;1055      if (name[1] == '1' && name[2] >= '4')1056        return true;1057      if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')1058        return true;1059    }1060 1061    if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp1062      return true;1063    if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp1064      return false;1065    if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc1066      return true;1067  }1068  return false;1069}1070 1071void ABISysV_ppc64::Initialize() {1072  PluginManager::RegisterPlugin(1073      GetPluginNameStatic(), "System V ABI for ppc64 targets", CreateInstance);1074}1075 1076void ABISysV_ppc64::Terminate() {1077  PluginManager::UnregisterPlugin(CreateInstance);1078}1079