brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.7 KiB · 29fd9f0 Raw
960 lines · cpp
1//===-- ABISysV_x86_64.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_x86_64.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/ADT/StringSwitch.h"13#include "llvm/TargetParser/Triple.h"14 15#include "lldb/Core/Module.h"16#include "lldb/Core/PluginManager.h"17#include "lldb/Core/Value.h"18#include "lldb/Symbol/UnwindPlan.h"19#include "lldb/Target/Process.h"20#include "lldb/Target/RegisterContext.h"21#include "lldb/Target/StackFrame.h"22#include "lldb/Target/Target.h"23#include "lldb/Target/Thread.h"24#include "lldb/Utility/ConstString.h"25#include "lldb/Utility/DataExtractor.h"26#include "lldb/Utility/LLDBLog.h"27#include "lldb/Utility/Log.h"28#include "lldb/Utility/RegisterValue.h"29#include "lldb/Utility/Status.h"30#include "lldb/ValueObject/ValueObjectConstResult.h"31#include "lldb/ValueObject/ValueObjectMemory.h"32#include "lldb/ValueObject/ValueObjectRegister.h"33 34#include <optional>35#include <vector>36 37using namespace lldb;38using namespace lldb_private;39 40LLDB_PLUGIN_DEFINE(ABISysV_x86_64)41 42enum dwarf_regnums {43  dwarf_rax = 0,44  dwarf_rdx,45  dwarf_rcx,46  dwarf_rbx,47  dwarf_rsi,48  dwarf_rdi,49  dwarf_rbp,50  dwarf_rsp,51  dwarf_r8,52  dwarf_r9,53  dwarf_r10,54  dwarf_r11,55  dwarf_r12,56  dwarf_r13,57  dwarf_r14,58  dwarf_r15,59  dwarf_rip,60};61 62bool ABISysV_x86_64::GetPointerReturnRegister(const char *&name) {63  name = "rax";64  return true;65}66 67size_t ABISysV_x86_64::GetRedZoneSize() const { return 128; }68 69// Static Functions70 71ABISP72ABISysV_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {73  const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();74  const llvm::Triple::OSType os_type = arch.GetTriple().getOS();75  const llvm::Triple::EnvironmentType os_env =76      arch.GetTriple().getEnvironment();77  if (arch_type == llvm::Triple::x86_64) {78    switch(os_type) {79    case llvm::Triple::OSType::IOS:80    case llvm::Triple::OSType::TvOS:81    case llvm::Triple::OSType::WatchOS:82    case llvm::Triple::OSType::XROS:83      switch (os_env) {84      case llvm::Triple::EnvironmentType::MacABI:85      case llvm::Triple::EnvironmentType::Simulator:86      case llvm::Triple::EnvironmentType::UnknownEnvironment:87        // UnknownEnvironment is needed for older compilers that don't88        // support the simulator environment.89        return ABISP(new ABISysV_x86_64(std::move(process_sp),90                                        MakeMCRegisterInfo(arch)));91      default:92        return ABISP();93      }94    case llvm::Triple::OSType::Darwin:95    case llvm::Triple::OSType::FreeBSD:96    case llvm::Triple::OSType::Linux:97    case llvm::Triple::OSType::MacOSX:98    case llvm::Triple::OSType::NetBSD:99    case llvm::Triple::OSType::OpenBSD:100    case llvm::Triple::OSType::Solaris:101    case llvm::Triple::OSType::UnknownOS:102      return ABISP(103          new ABISysV_x86_64(std::move(process_sp), MakeMCRegisterInfo(arch)));104    default:105      return ABISP();106    }107  }108  return ABISP();109}110 111bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp,112                                        addr_t func_addr, addr_t return_addr,113                                        llvm::ArrayRef<addr_t> args) const {114  Log *log = GetLog(LLDBLog::Expressions);115 116  if (log) {117    StreamString s;118    s.Printf("ABISysV_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64119             ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64120             ", return_addr = 0x%" PRIx64,121             thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,122             (uint64_t)return_addr);123 124    for (size_t i = 0; i < args.size(); ++i)125      s.Printf(", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1),126               args[i]);127    s.PutCString(")");128    log->PutString(s.GetString());129  }130 131  RegisterContext *reg_ctx = thread.GetRegisterContext().get();132  if (!reg_ctx)133    return false;134 135  const RegisterInfo *reg_info = nullptr;136 137  if (args.size() > 6) // TODO handle more than 6 arguments138    return false;139 140  for (size_t i = 0; i < args.size(); ++i) {141    reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,142                                        LLDB_REGNUM_GENERIC_ARG1 + i);143    LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s",144              static_cast<uint64_t>(i + 1), args[i], reg_info->name);145    if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))146      return false;147  }148 149  // First, align the SP150 151  LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,152            (uint64_t)sp, (uint64_t)(sp & ~0xfull));153 154  sp &= ~(0xfull); // 16-byte alignment155 156  sp -= 8;157 158  Status error;159  const RegisterInfo *pc_reg_info =160      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);161  const RegisterInfo *sp_reg_info =162      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);163  ProcessSP process_sp(thread.GetProcess());164 165  RegisterValue reg_value;166  LLDB_LOGF(log,167            "Pushing the return address onto the stack: 0x%" PRIx64168            ": 0x%" PRIx64,169            (uint64_t)sp, (uint64_t)return_addr);170 171  // Save return address onto the stack172  if (!process_sp->WritePointerToMemory(sp, return_addr, error))173    return false;174 175  // %rsp is set to the actual stack value.176 177  LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);178 179  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))180    return false;181 182  // %rip is set to the address of the called function.183 184  LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr);185 186  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))187    return false;188 189  return true;190}191 192static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,193                                bool is_signed, Thread &thread,194                                uint32_t *argument_register_ids,195                                unsigned int &current_argument_register,196                                addr_t &current_stack_argument) {197  if (bit_width > 64)198    return false; // Scalar can't hold large integer arguments199 200  if (current_argument_register < 6) {201    scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(202        argument_register_ids[current_argument_register], 0);203    current_argument_register++;204    if (is_signed)205      scalar.SignExtend(bit_width);206  } else {207    uint32_t byte_size = (bit_width + (8 - 1)) / 8;208    Status error;209    if (thread.GetProcess()->ReadScalarIntegerFromMemory(210            current_stack_argument, byte_size, is_signed, scalar, error)) {211      current_stack_argument += byte_size;212      return true;213    }214    return false;215  }216  return true;217}218 219bool ABISysV_x86_64::GetArgumentValues(Thread &thread,220                                       ValueList &values) const {221  unsigned int num_values = values.GetSize();222  unsigned int value_index;223 224  // Extract the register context so we can read arguments from registers225 226  RegisterContext *reg_ctx = thread.GetRegisterContext().get();227 228  if (!reg_ctx)229    return false;230 231  // Get the pointer to the first stack argument so we have a place to start232  // when reading data233 234  addr_t sp = reg_ctx->GetSP(0);235 236  if (!sp)237    return false;238 239  addr_t current_stack_argument = sp + 8; // jump over return address240 241  uint32_t argument_register_ids[6];242 243  argument_register_ids[0] =244      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)245          ->kinds[eRegisterKindLLDB];246  argument_register_ids[1] =247      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)248          ->kinds[eRegisterKindLLDB];249  argument_register_ids[2] =250      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)251          ->kinds[eRegisterKindLLDB];252  argument_register_ids[3] =253      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)254          ->kinds[eRegisterKindLLDB];255  argument_register_ids[4] =256      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)257          ->kinds[eRegisterKindLLDB];258  argument_register_ids[5] =259      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)260          ->kinds[eRegisterKindLLDB];261 262  unsigned int current_argument_register = 0;263 264  for (value_index = 0; value_index < num_values; ++value_index) {265    Value *value = values.GetValueAtIndex(value_index);266 267    if (!value)268      return false;269 270    // We currently only support extracting values with Clang QualTypes. Do we271    // care about others?272    CompilerType compiler_type = value->GetCompilerType();273    std::optional<uint64_t> bit_size =274        llvm::expectedToOptional(compiler_type.GetBitSize(&thread));275    if (!bit_size)276      return false;277    bool is_signed;278 279    if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {280      ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,281                          argument_register_ids, current_argument_register,282                          current_stack_argument);283    } else if (compiler_type.IsPointerType()) {284      ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,285                          argument_register_ids, current_argument_register,286                          current_stack_argument);287    }288  }289 290  return true;291}292 293Status ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,294                                            lldb::ValueObjectSP &new_value_sp) {295  Status error;296  if (!new_value_sp) {297    error = Status::FromErrorString("Empty value object for return value.");298    return error;299  }300 301  CompilerType compiler_type = new_value_sp->GetCompilerType();302  if (!compiler_type) {303    error = Status::FromErrorString("Null clang type for return value.");304    return error;305  }306 307  Thread *thread = frame_sp->GetThread().get();308 309  bool is_signed;310  bool is_complex;311 312  RegisterContext *reg_ctx = thread->GetRegisterContext().get();313 314  bool set_it_simple = false;315  if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||316      compiler_type.IsPointerType()) {317    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);318 319    DataExtractor data;320    Status data_error;321    size_t num_bytes = new_value_sp->GetData(data, data_error);322    if (data_error.Fail()) {323      error = Status::FromErrorStringWithFormat(324          "Couldn't convert return value to raw data: %s",325          data_error.AsCString());326      return error;327    }328    lldb::offset_t offset = 0;329    if (num_bytes <= 8) {330      uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);331 332      if (reg_ctx->WriteRegisterFromUnsigned(reg_info, raw_value))333        set_it_simple = true;334    } else {335      error = Status::FromErrorString(336          "We don't support returning longer than 64 bit "337          "integer values at present.");338    }339  } else if (compiler_type.IsFloatingPointType(is_complex)) {340    if (is_complex)341      error = Status::FromErrorString(342          "We don't support returning complex values at present");343    else {344      std::optional<uint64_t> bit_width =345          llvm::expectedToOptional(compiler_type.GetBitSize(frame_sp.get()));346      if (!bit_width) {347        error = Status::FromErrorString("can't get type size");348        return error;349      }350      if (*bit_width <= 64) {351        const RegisterInfo *xmm0_info =352            reg_ctx->GetRegisterInfoByName("xmm0", 0);353        RegisterValue xmm0_value;354        DataExtractor data;355        Status data_error;356        size_t num_bytes = new_value_sp->GetData(data, data_error);357        if (data_error.Fail()) {358          error = Status::FromErrorStringWithFormat(359              "Couldn't convert return value to raw data: %s",360              data_error.AsCString());361          return error;362        }363 364        unsigned char buffer[16];365        ByteOrder byte_order = data.GetByteOrder();366 367        data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order);368        xmm0_value.SetBytes(buffer, 16, byte_order);369        reg_ctx->WriteRegister(xmm0_info, xmm0_value);370        set_it_simple = true;371      } else {372        // FIXME - don't know how to do 80 bit long doubles yet.373        error = Status::FromErrorString(374            "We don't support returning float values > 64 bits at present");375      }376    }377  }378 379  if (!set_it_simple) {380    // Okay we've got a structure or something that doesn't fit in a simple381    // register. We should figure out where it really goes, but we don't382    // support this yet.383    error = Status::FromErrorString(384        "We only support setting simple integer and float "385        "return types at present.");386  }387 388  return error;389}390 391ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(392    Thread &thread, CompilerType &return_compiler_type) const {393  ValueObjectSP return_valobj_sp;394  Value value;395 396  if (!return_compiler_type)397    return return_valobj_sp;398 399  // value.SetContext (Value::eContextTypeClangType, return_value_type);400  value.SetCompilerType(return_compiler_type);401 402  RegisterContext *reg_ctx = thread.GetRegisterContext().get();403  if (!reg_ctx)404    return return_valobj_sp;405 406  const uint32_t type_flags = return_compiler_type.GetTypeInfo();407  if (type_flags & eTypeIsScalar) {408    value.SetValueType(Value::ValueType::Scalar);409 410    bool success = false;411    if (type_flags & eTypeIsInteger) {412      // Extract the register context so we can read arguments from registers413 414      std::optional<uint64_t> byte_size =415          llvm::expectedToOptional(return_compiler_type.GetByteSize(&thread));416      if (!byte_size)417        return return_valobj_sp;418      uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(419          reg_ctx->GetRegisterInfoByName("rax", 0), 0);420      const bool is_signed = (type_flags & eTypeIsSigned) != 0;421      switch (*byte_size) {422      default:423        break;424 425      case sizeof(uint64_t):426        if (is_signed)427          value.GetScalar() = (int64_t)(raw_value);428        else429          value.GetScalar() = (uint64_t)(raw_value);430        success = true;431        break;432 433      case sizeof(uint32_t):434        if (is_signed)435          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);436        else437          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);438        success = true;439        break;440 441      case sizeof(uint16_t):442        if (is_signed)443          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);444        else445          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);446        success = true;447        break;448 449      case sizeof(uint8_t):450        if (is_signed)451          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);452        else453          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);454        success = true;455        break;456      }457    } else if (type_flags & eTypeIsFloat) {458      if (type_flags & eTypeIsComplex) {459        // Don't handle complex yet.460      } else {461        std::optional<uint64_t> byte_size =462            llvm::expectedToOptional(return_compiler_type.GetByteSize(&thread));463        if (byte_size && *byte_size <= sizeof(long double)) {464          const RegisterInfo *xmm0_info =465              reg_ctx->GetRegisterInfoByName("xmm0", 0);466          RegisterValue xmm0_value;467          if (reg_ctx->ReadRegister(xmm0_info, xmm0_value)) {468            DataExtractor data;469            if (xmm0_value.GetData(data)) {470              lldb::offset_t offset = 0;471              if (*byte_size == sizeof(float)) {472                value.GetScalar() = (float)data.GetFloat(&offset);473                success = true;474              } else if (*byte_size == sizeof(double)) {475                value.GetScalar() = (double)data.GetDouble(&offset);476                success = true;477              } else if (*byte_size == sizeof(long double)) {478                // Don't handle long double since that can be encoded as 80 bit479                // floats...480              }481            }482          }483        }484      }485    }486 487    if (success)488      return_valobj_sp = ValueObjectConstResult::Create(489          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));490  } else if (type_flags & eTypeIsPointer) {491    unsigned rax_id =492        reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];493    value.GetScalar() =494        (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,495                                                                      0);496    value.SetValueType(Value::ValueType::Scalar);497    return_valobj_sp = ValueObjectConstResult::Create(498        thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));499  } else if (type_flags & eTypeIsVector) {500    std::optional<uint64_t> byte_size =501        llvm::expectedToOptional(return_compiler_type.GetByteSize(&thread));502    if (byte_size && *byte_size > 0) {503      const RegisterInfo *altivec_reg =504          reg_ctx->GetRegisterInfoByName("xmm0", 0);505      if (altivec_reg == nullptr)506        altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);507 508      if (altivec_reg) {509        if (*byte_size <= altivec_reg->byte_size) {510          ProcessSP process_sp(thread.GetProcess());511          if (process_sp) {512            std::unique_ptr<DataBufferHeap> heap_data_up(513                new DataBufferHeap(*byte_size, 0));514            const ByteOrder byte_order = process_sp->GetByteOrder();515            RegisterValue reg_value;516            if (reg_ctx->ReadRegister(altivec_reg, reg_value)) {517              Status error;518              if (reg_value.GetAsMemoryData(519                      *altivec_reg, heap_data_up->GetBytes(),520                      heap_data_up->GetByteSize(), byte_order, error)) {521                DataExtractor data(DataBufferSP(heap_data_up.release()),522                                   byte_order,523                                   process_sp->GetTarget()524                                       .GetArchitecture()525                                       .GetAddressByteSize());526                return_valobj_sp = ValueObjectConstResult::Create(527                    &thread, return_compiler_type, ConstString(""), data);528              }529            }530          }531        } else if (*byte_size <= altivec_reg->byte_size * 2) {532          const RegisterInfo *altivec_reg2 =533              reg_ctx->GetRegisterInfoByName("xmm1", 0);534          if (altivec_reg2) {535            ProcessSP process_sp(thread.GetProcess());536            if (process_sp) {537              std::unique_ptr<DataBufferHeap> heap_data_up(538                  new DataBufferHeap(*byte_size, 0));539              const ByteOrder byte_order = process_sp->GetByteOrder();540              RegisterValue reg_value;541              RegisterValue reg_value2;542              if (reg_ctx->ReadRegister(altivec_reg, reg_value) &&543                  reg_ctx->ReadRegister(altivec_reg2, reg_value2)) {544 545                Status error;546                if (reg_value.GetAsMemoryData(547                        *altivec_reg, heap_data_up->GetBytes(),548                        altivec_reg->byte_size, byte_order, error) &&549                    reg_value2.GetAsMemoryData(550                        *altivec_reg2,551                        heap_data_up->GetBytes() + altivec_reg->byte_size,552                        heap_data_up->GetByteSize() - altivec_reg->byte_size,553                        byte_order, error)) {554                  DataExtractor data(DataBufferSP(heap_data_up.release()),555                                     byte_order,556                                     process_sp->GetTarget()557                                         .GetArchitecture()558                                         .GetAddressByteSize());559                  return_valobj_sp = ValueObjectConstResult::Create(560                      &thread, return_compiler_type, ConstString(""), data);561                }562              }563            }564          }565        }566      }567    }568  }569 570  return return_valobj_sp;571}572 573// The compiler will flatten the nested aggregate type into single574// layer and push the value to stack575// This helper function will flatten an aggregate type576// and return true if it can be returned in register(s) by value577// return false if the aggregate is in memory578static bool FlattenAggregateType(579    Thread &thread, ExecutionContext &exe_ctx,580    CompilerType &return_compiler_type,581    uint32_t data_byte_offset,582    std::vector<uint32_t> &aggregate_field_offsets,583    std::vector<CompilerType> &aggregate_compiler_types) {584 585  const uint32_t num_children = return_compiler_type.GetNumFields();586  for (uint32_t idx = 0; idx < num_children; ++idx) {587    std::string name;588    bool is_signed;589    bool is_complex;590 591    uint64_t field_bit_offset = 0;592    CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(593        idx, name, &field_bit_offset, nullptr, nullptr);594    std::optional<uint64_t> field_bit_width =595        llvm::expectedToOptional(field_compiler_type.GetBitSize(&thread));596 597    // if we don't know the size of the field (e.g. invalid type), exit598    if (!field_bit_width || *field_bit_width == 0) {599      return false;600    }601 602    uint32_t field_byte_offset = field_bit_offset / 8 + data_byte_offset;603 604    const uint32_t field_type_flags = field_compiler_type.GetTypeInfo();605    if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||606        field_compiler_type.IsPointerType() ||607        field_compiler_type.IsFloatingPointType(is_complex)) {608      aggregate_field_offsets.push_back(field_byte_offset);609      aggregate_compiler_types.push_back(field_compiler_type);610    } else if (field_type_flags & eTypeHasChildren) {611      if (!FlattenAggregateType(thread, exe_ctx, field_compiler_type,612                                field_byte_offset, aggregate_field_offsets,613                                aggregate_compiler_types)) {614        return false;615      }616    }617  }618  return true;619}620 621ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(622    Thread &thread, CompilerType &return_compiler_type) const {623  ValueObjectSP return_valobj_sp;624 625  if (!return_compiler_type)626    return return_valobj_sp;627 628  ExecutionContext exe_ctx(thread.shared_from_this());629  return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);630  if (return_valobj_sp)631    return return_valobj_sp;632 633  RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();634  if (!reg_ctx_sp)635    return return_valobj_sp;636 637  std::optional<uint64_t> bit_width =638      llvm::expectedToOptional(return_compiler_type.GetBitSize(&thread));639  if (!bit_width)640    return return_valobj_sp;641  if (return_compiler_type.IsAggregateType()) {642    Target *target = exe_ctx.GetTargetPtr();643    bool is_memory = true;644    std::vector<uint32_t> aggregate_field_offsets;645    std::vector<CompilerType> aggregate_compiler_types;646    auto ts = return_compiler_type.GetTypeSystem();647    if (ts && ts->CanPassInRegisters(return_compiler_type) &&648        *bit_width <= 128 &&649        FlattenAggregateType(thread, exe_ctx, return_compiler_type, 0,650                             aggregate_field_offsets,651                             aggregate_compiler_types)) {652      ByteOrder byte_order = target->GetArchitecture().GetByteOrder();653      WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));654      DataExtractor return_ext(data_sp, byte_order,655                               target->GetArchitecture().GetAddressByteSize());656 657      const RegisterInfo *rax_info =658          reg_ctx_sp->GetRegisterInfoByName("rax", 0);659      const RegisterInfo *rdx_info =660          reg_ctx_sp->GetRegisterInfoByName("rdx", 0);661      const RegisterInfo *xmm0_info =662          reg_ctx_sp->GetRegisterInfoByName("xmm0", 0);663      const RegisterInfo *xmm1_info =664          reg_ctx_sp->GetRegisterInfoByName("xmm1", 0);665 666      RegisterValue rax_value, rdx_value, xmm0_value, xmm1_value;667      reg_ctx_sp->ReadRegister(rax_info, rax_value);668      reg_ctx_sp->ReadRegister(rdx_info, rdx_value);669      reg_ctx_sp->ReadRegister(xmm0_info, xmm0_value);670      reg_ctx_sp->ReadRegister(xmm1_info, xmm1_value);671 672      DataExtractor rax_data, rdx_data, xmm0_data, xmm1_data;673 674      rax_value.GetData(rax_data);675      rdx_value.GetData(rdx_data);676      xmm0_value.GetData(xmm0_data);677      xmm1_value.GetData(xmm1_data);678 679      uint32_t fp_bytes =680          0; // Tracks how much of the xmm registers we've consumed so far681      uint32_t integer_bytes =682          0; // Tracks how much of the rax/rds registers we've consumed so far683 684      // in case of the returned type is a subclass of non-abstract-base class685      // it will have a padding to skip the base content686      if (aggregate_field_offsets.size()) {687        fp_bytes = aggregate_field_offsets[0];688        integer_bytes = aggregate_field_offsets[0];689      }690 691      const uint32_t num_children = aggregate_compiler_types.size();692 693      // Since we are in the small struct regime, assume we are not in memory.694      is_memory = false;695      for (uint32_t idx = 0; idx < num_children; idx++) {696        bool is_signed;697        bool is_complex;698 699        CompilerType field_compiler_type = aggregate_compiler_types[idx];700        uint32_t field_byte_width =701            (uint32_t)(llvm::expectedToOptional(702                           field_compiler_type.GetByteSize(&thread))703                           .value_or(0));704        uint32_t field_byte_offset = aggregate_field_offsets[idx];705 706        uint32_t field_bit_width = field_byte_width * 8;707 708        DataExtractor *copy_from_extractor = nullptr;709        uint32_t copy_from_offset = 0;710 711        if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||712            field_compiler_type.IsPointerType()) {713          if (integer_bytes < 8) {714            if (integer_bytes + field_byte_width <= 8) {715              // This is in RAX, copy from register to our result structure:716              copy_from_extractor = &rax_data;717              copy_from_offset = integer_bytes;718              integer_bytes += field_byte_width;719            } else {720              // The next field wouldn't fit in the remaining space, so we721              // pushed it to rdx.722              copy_from_extractor = &rdx_data;723              copy_from_offset = 0;724              integer_bytes = 8 + field_byte_width;725            }726          } else if (integer_bytes + field_byte_width <= 16) {727            copy_from_extractor = &rdx_data;728            copy_from_offset = integer_bytes - 8;729            integer_bytes += field_byte_width;730          } else {731            // The last field didn't fit.  I can't see how that would happen732            // w/o the overall size being greater than 16 bytes.  For now,733            // return a nullptr return value object.734            return return_valobj_sp;735          }736        } else if (field_compiler_type.IsFloatingPointType(is_complex)) {737          // Structs with long doubles are always passed in memory.738          if (field_bit_width == 128) {739            is_memory = true;740            break;741          } else if (field_bit_width == 64) {742            // These have to be in a single xmm register.743            if (fp_bytes == 0)744              copy_from_extractor = &xmm0_data;745            else746              copy_from_extractor = &xmm1_data;747 748            copy_from_offset = 0;749            fp_bytes += field_byte_width;750          } else if (field_bit_width == 32) {751            // This one is kind of complicated.  If we are in an "eightbyte"752            // with another float, we'll be stuffed into an xmm register with753            // it.  If we are in an "eightbyte" with one or more ints, then we754            // will be stuffed into the appropriate GPR with them.755            bool in_gpr;756            if (field_byte_offset % 8 == 0) {757              // We are at the beginning of one of the eightbytes, so check the758              // next element (if any)759              if (idx == num_children - 1) {760                in_gpr = false;761              } else {762                CompilerType next_field_compiler_type =763                    aggregate_compiler_types[idx + 1];764                if (next_field_compiler_type.IsIntegerOrEnumerationType(765                        is_signed)) {766                  in_gpr = true;767                } else {768                  copy_from_offset = 0;769                  in_gpr = false;770                }771              }772            } else if (field_byte_offset % 4 == 0) {773              // We are inside of an eightbyte, so see if the field before us774              // is floating point: This could happen if somebody put padding775              // in the structure.776              if (idx == 0) {777                in_gpr = false;778              } else {779                CompilerType prev_field_compiler_type =780                    aggregate_compiler_types[idx - 1];781                if (prev_field_compiler_type.IsIntegerOrEnumerationType(782                        is_signed)) {783                  in_gpr = true;784                } else {785                  copy_from_offset = 4;786                  in_gpr = false;787                }788              }789            } else {790              is_memory = true;791              continue;792            }793 794            // Okay, we've figured out whether we are in GPR or XMM, now figure795            // out which one.796            if (in_gpr) {797              if (integer_bytes < 8) {798                // This is in RAX, copy from register to our result structure:799                copy_from_extractor = &rax_data;800                copy_from_offset = integer_bytes;801                integer_bytes += field_byte_width;802              } else {803                copy_from_extractor = &rdx_data;804                copy_from_offset = integer_bytes - 8;805                integer_bytes += field_byte_width;806              }807            } else {808              if (fp_bytes < 8)809                copy_from_extractor = &xmm0_data;810              else811                copy_from_extractor = &xmm1_data;812 813              fp_bytes += field_byte_width;814            }815          }816        }817        // These two tests are just sanity checks.  If I somehow get the type818        // calculation wrong above it is better to just return nothing than to819        // assert or crash.820        if (!copy_from_extractor)821          return return_valobj_sp;822        if (copy_from_offset + field_byte_width >823            copy_from_extractor->GetByteSize())824          return return_valobj_sp;825        copy_from_extractor->CopyByteOrderedData(826            copy_from_offset, field_byte_width,827            data_sp->GetBytes() + field_byte_offset, field_byte_width,828            byte_order);829      }830      if (!is_memory) {831        // The result is in our data buffer.  Let's make a variable object out832        // of it:833        return_valobj_sp = ValueObjectConstResult::Create(834            &thread, return_compiler_type, ConstString(""), return_ext);835      }836    }837 838    // FIXME: This is just taking a guess, rax may very well no longer hold the839    // return storage location.840    // If we are going to do this right, when we make a new frame we should841    // check to see if it uses a memory return, and if we are at the first842    // instruction and if so stash away the return location.  Then we would843    // only return the memory return value if we know it is valid.844 845    if (is_memory) {846      unsigned rax_id =847          reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];848      lldb::addr_t storage_addr =849          (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,850                                                                        0);851      return_valobj_sp = ValueObjectMemory::Create(852          &thread, "", Address(storage_addr, nullptr), return_compiler_type);853    }854  }855 856  return return_valobj_sp;857}858 859// This defines the CFA as rsp+8860// the saved pc is at CFA-8 (i.e. rsp+0)861// The saved rsp is CFA+0862 863UnwindPlanSP ABISysV_x86_64::CreateFunctionEntryUnwindPlan() {864  uint32_t sp_reg_num = dwarf_rsp;865  uint32_t pc_reg_num = dwarf_rip;866 867  UnwindPlan::Row row;868  row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);869  row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);870  row.SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);871 872  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);873  plan_sp->AppendRow(std::move(row));874  plan_sp->SetSourceName("x86_64 at-func-entry default");875  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);876  return plan_sp;877}878 879// This defines the CFA as rbp+16880// The saved pc is at CFA-8 (i.e. rbp+8)881// The saved rbp is at CFA-16 (i.e. rbp+0)882// The saved rsp is CFA+0883 884UnwindPlanSP ABISysV_x86_64::CreateDefaultUnwindPlan() {885  uint32_t fp_reg_num = dwarf_rbp;886  uint32_t sp_reg_num = dwarf_rsp;887  uint32_t pc_reg_num = dwarf_rip;888 889  UnwindPlan::Row row;890 891  const int32_t ptr_size = 8;892  row.GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);893  row.SetOffset(0);894  row.SetUnspecifiedRegistersAreUndefined(true);895 896  row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);897  row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);898  row.SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);899 900  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);901  plan_sp->AppendRow(std::move(row));902  plan_sp->SetSourceName("x86_64 default unwind plan");903  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);904  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);905  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);906  return plan_sp;907}908 909bool ABISysV_x86_64::RegisterIsVolatile(const RegisterInfo *reg_info) {910  return !RegisterIsCalleeSaved(reg_info);911}912 913// See "Register Usage" in the914// "System V Application Binary Interface"915// "AMD64 Architecture Processor Supplement" (or "x86-64(tm) Architecture916// Processor Supplement" in earlier revisions) (this doc is also commonly917// referred to as the x86-64/AMD64 psABI) Edited by Michael Matz, Jan Hubicka,918// Andreas Jaeger, and Mark Mitchell current version is 0.99.6 released919// 2012-07-02 at http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf920// It's being revised & updated at https://github.com/hjl-tools/x86-psABI/921 922bool ABISysV_x86_64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {923  if (!reg_info)924    return false;925  assert(reg_info->name != nullptr && "unnamed register?");926  std::string Name = std::string(reg_info->name);927  bool IsCalleeSaved =928      llvm::StringSwitch<bool>(Name)929          .Cases({"r12", "r13", "r14", "r15", "rbp", "ebp", "rbx", "ebx"}, true)930          .Cases({"rip", "eip", "rsp", "esp", "sp", "fp", "pc"}, true)931          .Default(false);932  return IsCalleeSaved;933}934 935uint32_t ABISysV_x86_64::GetGenericNum(llvm::StringRef name) {936  return llvm::StringSwitch<uint32_t>(name)937      .Case("rip", LLDB_REGNUM_GENERIC_PC)938      .Case("rsp", LLDB_REGNUM_GENERIC_SP)939      .Case("rbp", LLDB_REGNUM_GENERIC_FP)940      .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS)941      // gdbserver uses eflags942      .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS)943      .Case("rdi", LLDB_REGNUM_GENERIC_ARG1)944      .Case("rsi", LLDB_REGNUM_GENERIC_ARG2)945      .Case("rdx", LLDB_REGNUM_GENERIC_ARG3)946      .Case("rcx", LLDB_REGNUM_GENERIC_ARG4)947      .Case("r8", LLDB_REGNUM_GENERIC_ARG5)948      .Case("r9", LLDB_REGNUM_GENERIC_ARG6)949      .Default(LLDB_INVALID_REGNUM);950}951 952void ABISysV_x86_64::Initialize() {953  PluginManager::RegisterPlugin(954      GetPluginNameStatic(), "System V ABI for x86_64 targets", CreateInstance);955}956 957void ABISysV_x86_64::Terminate() {958  PluginManager::UnregisterPlugin(CreateInstance);959}960