Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
39654 views
//===-- ABISysV_arm64.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "ABISysV_arm64.h"910#include <optional>11#include <vector>1213#include "llvm/ADT/STLExtras.h"14#include "llvm/TargetParser/Triple.h"1516#include "lldb/Core/Module.h"17#include "lldb/Core/PluginManager.h"18#include "lldb/Core/Value.h"19#include "lldb/Core/ValueObjectConstResult.h"20#include "lldb/Symbol/UnwindPlan.h"21#include "lldb/Target/Process.h"22#include "lldb/Target/RegisterContext.h"23#include "lldb/Target/Target.h"24#include "lldb/Target/Thread.h"25#include "lldb/Utility/ConstString.h"26#include "lldb/Utility/LLDBLog.h"27#include "lldb/Utility/Log.h"28#include "lldb/Utility/RegisterValue.h"29#include "lldb/Utility/Scalar.h"30#include "lldb/Utility/Status.h"3132#include "Utility/ARM64_DWARF_Registers.h"3334using namespace lldb;35using namespace lldb_private;3637bool ABISysV_arm64::GetPointerReturnRegister(const char *&name) {38name = "x0";39return true;40}4142size_t ABISysV_arm64::GetRedZoneSize() const { return 128; }4344// Static Functions4546ABISP47ABISysV_arm64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {48const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();49const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();5051if (vendor_type != llvm::Triple::Apple) {52if (arch_type == llvm::Triple::aarch64 ||53arch_type == llvm::Triple::aarch64_32) {54return ABISP(55new ABISysV_arm64(std::move(process_sp), MakeMCRegisterInfo(arch)));56}57}5859return ABISP();60}6162bool ABISysV_arm64::PrepareTrivialCall(Thread &thread, addr_t sp,63addr_t func_addr, addr_t return_addr,64llvm::ArrayRef<addr_t> args) const {65RegisterContext *reg_ctx = thread.GetRegisterContext().get();66if (!reg_ctx)67return false;6869Log *log = GetLog(LLDBLog::Expressions);7071if (log) {72StreamString s;73s.Printf("ABISysV_arm64::PrepareTrivialCall (tid = 0x%" PRIx6474", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx6475", return_addr = 0x%" PRIx64,76thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,77(uint64_t)return_addr);7879for (size_t i = 0; i < args.size(); ++i)80s.Printf(", arg%d = 0x%" PRIx64, static_cast<int>(i + 1), args[i]);81s.PutCString(")");82log->PutString(s.GetString());83}8485// x0 - x7 contain first 8 simple args86if (args.size() > 8)87return false;8889for (size_t i = 0; i < args.size(); ++i) {90const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(91eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);92LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s",93static_cast<int>(i + 1), args[i], reg_info->name);94if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))95return false;96}9798// Set "lr" to the return address99if (!reg_ctx->WriteRegisterFromUnsigned(100reg_ctx->GetRegisterInfo(eRegisterKindGeneric,101LLDB_REGNUM_GENERIC_RA),102return_addr))103return false;104105// Set "sp" to the requested value106if (!reg_ctx->WriteRegisterFromUnsigned(107reg_ctx->GetRegisterInfo(eRegisterKindGeneric,108LLDB_REGNUM_GENERIC_SP),109sp))110return false;111112// Set "pc" to the address requested113if (!reg_ctx->WriteRegisterFromUnsigned(114reg_ctx->GetRegisterInfo(eRegisterKindGeneric,115LLDB_REGNUM_GENERIC_PC),116func_addr))117return false;118119return true;120}121122// TODO: We dont support fp/SIMD arguments in v0-v7123bool ABISysV_arm64::GetArgumentValues(Thread &thread, ValueList &values) const {124uint32_t num_values = values.GetSize();125126ExecutionContext exe_ctx(thread.shared_from_this());127128// Extract the register context so we can read arguments from registers129130RegisterContext *reg_ctx = thread.GetRegisterContext().get();131132if (!reg_ctx)133return false;134135addr_t sp = 0;136137for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {138// We currently only support extracting values with Clang QualTypes. Do we139// care about others?140Value *value = values.GetValueAtIndex(value_idx);141142if (!value)143return false;144145CompilerType value_type = value->GetCompilerType();146if (value_type) {147bool is_signed = false;148size_t bit_width = 0;149std::optional<uint64_t> bit_size = value_type.GetBitSize(&thread);150if (!bit_size)151return false;152if (value_type.IsIntegerOrEnumerationType(is_signed)) {153bit_width = *bit_size;154} else if (value_type.IsPointerOrReferenceType()) {155bit_width = *bit_size;156} else {157// We only handle integer, pointer and reference types currently...158return false;159}160161if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) {162if (value_idx < 8) {163// Arguments 1-8 are in x0-x7...164const RegisterInfo *reg_info = nullptr;165reg_info = reg_ctx->GetRegisterInfo(166eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);167168if (reg_info) {169RegisterValue reg_value;170171if (reg_ctx->ReadRegister(reg_info, reg_value)) {172if (is_signed)173reg_value.SignExtend(bit_width);174if (!reg_value.GetScalarValue(value->GetScalar()))175return false;176continue;177}178}179return false;180} else {181// TODO: Verify for stack layout for SysV182if (sp == 0) {183// Read the stack pointer if we already haven't read it184sp = reg_ctx->GetSP(0);185if (sp == 0)186return false;187}188189// Arguments 5 on up are on the stack190const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8;191Status error;192if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(193sp, arg_byte_size, is_signed, value->GetScalar(), error))194return false;195196sp += arg_byte_size;197// Align up to the next 8 byte boundary if needed198if (sp % 8) {199sp >>= 3;200sp += 1;201sp <<= 3;202}203}204}205}206}207return true;208}209210Status ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,211lldb::ValueObjectSP &new_value_sp) {212Status error;213if (!new_value_sp) {214error.SetErrorString("Empty value object for return value.");215return error;216}217218CompilerType return_value_type = new_value_sp->GetCompilerType();219if (!return_value_type) {220error.SetErrorString("Null clang type for return value.");221return error;222}223224Thread *thread = frame_sp->GetThread().get();225226RegisterContext *reg_ctx = thread->GetRegisterContext().get();227228if (reg_ctx) {229DataExtractor data;230Status data_error;231const uint64_t byte_size = new_value_sp->GetData(data, data_error);232if (data_error.Fail()) {233error.SetErrorStringWithFormat(234"Couldn't convert return value to raw data: %s",235data_error.AsCString());236return error;237}238239const uint32_t type_flags = return_value_type.GetTypeInfo(nullptr);240if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {241if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {242// Extract the register context so we can read arguments from registers243lldb::offset_t offset = 0;244if (byte_size <= 16) {245const RegisterInfo *x0_info = reg_ctx->GetRegisterInfo(246eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);247if (byte_size <= 8) {248uint64_t raw_value = data.GetMaxU64(&offset, byte_size);249250if (!reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value))251error.SetErrorString("failed to write register x0");252} else {253uint64_t raw_value = data.GetMaxU64(&offset, 8);254255if (reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value)) {256const RegisterInfo *x1_info = reg_ctx->GetRegisterInfo(257eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);258raw_value = data.GetMaxU64(&offset, byte_size - offset);259260if (!reg_ctx->WriteRegisterFromUnsigned(x1_info, raw_value))261error.SetErrorString("failed to write register x1");262}263}264} else {265error.SetErrorString("We don't support returning longer than 128 bit "266"integer values at present.");267}268} else if (type_flags & eTypeIsFloat) {269if (type_flags & eTypeIsComplex) {270// Don't handle complex yet.271error.SetErrorString(272"returning complex float values are not supported");273} else {274const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);275276if (v0_info) {277if (byte_size <= 16) {278RegisterValue reg_value;279error = reg_value.SetValueFromData(*v0_info, data, 0, true);280if (error.Success())281if (!reg_ctx->WriteRegister(v0_info, reg_value))282error.SetErrorString("failed to write register v0");283} else {284error.SetErrorString("returning float values longer than 128 "285"bits are not supported");286}287} else288error.SetErrorString("v0 register is not available on this target");289}290}291} else if (type_flags & eTypeIsVector) {292if (byte_size > 0) {293const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);294295if (v0_info) {296if (byte_size <= v0_info->byte_size) {297RegisterValue reg_value;298error = reg_value.SetValueFromData(*v0_info, data, 0, true);299if (error.Success()) {300if (!reg_ctx->WriteRegister(v0_info, reg_value))301error.SetErrorString("failed to write register v0");302}303}304}305}306}307} else {308error.SetErrorString("no registers are available");309}310311return error;312}313314bool ABISysV_arm64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {315unwind_plan.Clear();316unwind_plan.SetRegisterKind(eRegisterKindDWARF);317318uint32_t lr_reg_num = arm64_dwarf::lr;319uint32_t sp_reg_num = arm64_dwarf::sp;320321UnwindPlan::RowSP row(new UnwindPlan::Row);322323// Our previous Call Frame Address is the stack pointer324row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);325326unwind_plan.AppendRow(row);327unwind_plan.SetReturnAddressRegister(lr_reg_num);328329// All other registers are the same.330331unwind_plan.SetSourceName("arm64 at-func-entry default");332unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);333unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);334unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);335336return true;337}338339bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {340unwind_plan.Clear();341unwind_plan.SetRegisterKind(eRegisterKindDWARF);342343uint32_t fp_reg_num = arm64_dwarf::fp;344uint32_t pc_reg_num = arm64_dwarf::pc;345346UnwindPlan::RowSP row(new UnwindPlan::Row);347const int32_t ptr_size = 8;348349row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);350row->SetOffset(0);351row->SetUnspecifiedRegistersAreUndefined(true);352353row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);354row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);355356unwind_plan.AppendRow(row);357unwind_plan.SetSourceName("arm64 default unwind plan");358unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);359unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);360unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);361362return true;363}364365// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says366// registers x19 through x28 and sp are callee preserved. v8-v15 are non-367// volatile (and specifically only the lower 8 bytes of these regs), the rest368// of the fp/SIMD registers are volatile.369370// We treat x29 as callee preserved also, else the unwinder won't try to371// retrieve fp saves.372373bool ABISysV_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) {374if (reg_info) {375const char *name = reg_info->name;376377// Sometimes we'll be called with the "alternate" name for these registers;378// recognize them as non-volatile.379380if (name[0] == 'p' && name[1] == 'c') // pc381return false;382if (name[0] == 'f' && name[1] == 'p') // fp383return false;384if (name[0] == 's' && name[1] == 'p') // sp385return false;386if (name[0] == 'l' && name[1] == 'r') // lr387return false;388389if (name[0] == 'x' || name[0] == 'r') {390// Volatile registers: x0-x18391// Although documentation says only x19-28 + sp are callee saved We ll392// also have to treat x30 as non-volatile. Each dwarf frame has its own393// value of lr. Return false for the non-volatile gpr regs, true for394// everything else395switch (name[1]) {396case '1':397switch (name[2]) {398case '9':399return false; // x19 is non-volatile400default:401return true;402}403break;404case '2':405switch (name[2]) {406case '0':407case '1':408case '2':409case '3':410case '4':411case '5':412case '6':413case '7':414case '8':415return false; // x20 - 28 are non-volatile416case '9':417return false; // x29 aka fp treat as non-volatile418default:419return true;420}421case '3': // x30 (lr) and x31 (sp) treat as non-volatile422if (name[2] == '0' || name[2] == '1')423return false;424break;425default:426return true; // all volatile cases not handled above fall here.427}428} else if (name[0] == 'v' || name[0] == 's' || name[0] == 'd') {429// Volatile registers: v0-7, v16-v31430// Return false for non-volatile fp/SIMD regs, true for everything else431switch (name[1]) {432case '8':433case '9':434return false; // v8-v9 are non-volatile435case '1':436switch (name[2]) {437case '0':438case '1':439case '2':440case '3':441case '4':442case '5':443return false; // v10-v15 are non-volatile444default:445return true;446}447default:448return true;449}450}451}452return true;453}454455static bool LoadValueFromConsecutiveGPRRegisters(456ExecutionContext &exe_ctx, RegisterContext *reg_ctx,457const CompilerType &value_type,458bool is_return_value, // false => parameter, true => return value459uint32_t &NGRN, // NGRN (see ABI documentation)460uint32_t &NSRN, // NSRN (see ABI documentation)461DataExtractor &data) {462std::optional<uint64_t> byte_size =463value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());464465if (byte_size || *byte_size == 0)466return false;467468std::unique_ptr<DataBufferHeap> heap_data_up(469new DataBufferHeap(*byte_size, 0));470const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();471Status error;472473CompilerType base_type;474const uint32_t homogeneous_count =475value_type.IsHomogeneousAggregate(&base_type);476if (homogeneous_count > 0 && homogeneous_count <= 8) {477// Make sure we have enough registers478if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) {479if (!base_type)480return false;481std::optional<uint64_t> base_byte_size =482base_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());483if (!base_byte_size)484return false;485uint32_t data_offset = 0;486487for (uint32_t i = 0; i < homogeneous_count; ++i) {488char v_name[8];489::snprintf(v_name, sizeof(v_name), "v%u", NSRN);490const RegisterInfo *reg_info =491reg_ctx->GetRegisterInfoByName(v_name, 0);492if (reg_info == nullptr)493return false;494495if (*base_byte_size > reg_info->byte_size)496return false;497498RegisterValue reg_value;499500if (!reg_ctx->ReadRegister(reg_info, reg_value))501return false;502503// Make sure we have enough room in "heap_data_up"504if ((data_offset + *base_byte_size) <= heap_data_up->GetByteSize()) {505const size_t bytes_copied = reg_value.GetAsMemoryData(506*reg_info, heap_data_up->GetBytes() + data_offset,507*base_byte_size, byte_order, error);508if (bytes_copied != *base_byte_size)509return false;510data_offset += bytes_copied;511++NSRN;512} else513return false;514}515data.SetByteOrder(byte_order);516data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());517data.SetData(DataBufferSP(heap_data_up.release()));518return true;519}520}521522const size_t max_reg_byte_size = 16;523if (*byte_size <= max_reg_byte_size) {524size_t bytes_left = *byte_size;525uint32_t data_offset = 0;526while (data_offset < *byte_size) {527if (NGRN >= 8)528return false;529530const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(531eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);532if (reg_info == nullptr)533return false;534535RegisterValue reg_value;536537if (!reg_ctx->ReadRegister(reg_info, reg_value))538return false;539540const size_t curr_byte_size = std::min<size_t>(8, bytes_left);541const size_t bytes_copied = reg_value.GetAsMemoryData(542*reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size,543byte_order, error);544if (bytes_copied == 0)545return false;546if (bytes_copied >= bytes_left)547break;548data_offset += bytes_copied;549bytes_left -= bytes_copied;550++NGRN;551}552} else {553const RegisterInfo *reg_info = nullptr;554if (is_return_value) {555// The SysV arm64 ABI doesn't require you to write the return location556// back to x8 before returning from the function the way the x86_64 ABI557// does. It looks like all the users of this ABI currently choose not to558// do that, and so we can't reconstruct stack based returns on exit559// from the function.560return false;561} else {562// We are assuming we are stopped at the first instruction in a function563// and that the ABI is being respected so all parameters appear where564// they should be (functions with no external linkage can legally violate565// the ABI).566if (NGRN >= 8)567return false;568569reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,570LLDB_REGNUM_GENERIC_ARG1 + NGRN);571if (reg_info == nullptr)572return false;573++NGRN;574}575576const lldb::addr_t value_addr =577reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS);578579if (value_addr == LLDB_INVALID_ADDRESS)580return false;581582if (exe_ctx.GetProcessRef().ReadMemory(583value_addr, heap_data_up->GetBytes(), heap_data_up->GetByteSize(),584error) != heap_data_up->GetByteSize()) {585return false;586}587}588589data.SetByteOrder(byte_order);590data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());591data.SetData(DataBufferSP(heap_data_up.release()));592return true;593}594595ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(596Thread &thread, CompilerType &return_compiler_type) const {597ValueObjectSP return_valobj_sp;598Value value;599600ExecutionContext exe_ctx(thread.shared_from_this());601if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)602return return_valobj_sp;603604// value.SetContext (Value::eContextTypeClangType, return_compiler_type);605value.SetCompilerType(return_compiler_type);606607RegisterContext *reg_ctx = thread.GetRegisterContext().get();608if (!reg_ctx)609return return_valobj_sp;610611std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread);612if (!byte_size)613return return_valobj_sp;614615const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);616if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {617value.SetValueType(Value::ValueType::Scalar);618619bool success = false;620if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {621// Extract the register context so we can read arguments from registers622if (*byte_size <= 8) {623const RegisterInfo *x0_reg_info = nullptr;624x0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,625LLDB_REGNUM_GENERIC_ARG1);626if (x0_reg_info) {627uint64_t raw_value =628thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info,6290);630const bool is_signed = (type_flags & eTypeIsSigned) != 0;631switch (*byte_size) {632default:633break;634case 16: // uint128_t635// In register x0 and x1636{637const RegisterInfo *x1_reg_info = nullptr;638x1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,639LLDB_REGNUM_GENERIC_ARG2);640641if (x1_reg_info) {642if (*byte_size <=643x0_reg_info->byte_size + x1_reg_info->byte_size) {644std::unique_ptr<DataBufferHeap> heap_data_up(645new DataBufferHeap(*byte_size, 0));646const ByteOrder byte_order =647exe_ctx.GetProcessRef().GetByteOrder();648RegisterValue x0_reg_value;649RegisterValue x1_reg_value;650if (reg_ctx->ReadRegister(x0_reg_info, x0_reg_value) &&651reg_ctx->ReadRegister(x1_reg_info, x1_reg_value)) {652Status error;653if (x0_reg_value.GetAsMemoryData(654*x0_reg_info, heap_data_up->GetBytes() + 0, 8,655byte_order, error) &&656x1_reg_value.GetAsMemoryData(657*x1_reg_info, heap_data_up->GetBytes() + 8, 8,658byte_order, error)) {659DataExtractor data(660DataBufferSP(heap_data_up.release()), byte_order,661exe_ctx.GetProcessRef().GetAddressByteSize());662663return_valobj_sp = ValueObjectConstResult::Create(664&thread, return_compiler_type, ConstString(""), data);665return return_valobj_sp;666}667}668}669}670}671break;672case sizeof(uint64_t):673if (is_signed)674value.GetScalar() = (int64_t)(raw_value);675else676value.GetScalar() = (uint64_t)(raw_value);677success = true;678break;679680case sizeof(uint32_t):681if (is_signed)682value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);683else684value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);685success = true;686break;687688case sizeof(uint16_t):689if (is_signed)690value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);691else692value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);693success = true;694break;695696case sizeof(uint8_t):697if (is_signed)698value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);699else700value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);701success = true;702break;703}704}705}706} else if (type_flags & eTypeIsFloat) {707if (type_flags & eTypeIsComplex) {708// Don't handle complex yet.709} else {710if (*byte_size <= sizeof(long double)) {711const RegisterInfo *v0_reg_info =712reg_ctx->GetRegisterInfoByName("v0", 0);713RegisterValue v0_value;714if (reg_ctx->ReadRegister(v0_reg_info, v0_value)) {715DataExtractor data;716if (v0_value.GetData(data)) {717lldb::offset_t offset = 0;718if (*byte_size == sizeof(float)) {719value.GetScalar() = data.GetFloat(&offset);720success = true;721} else if (*byte_size == sizeof(double)) {722value.GetScalar() = data.GetDouble(&offset);723success = true;724} else if (*byte_size == sizeof(long double)) {725value.GetScalar() = data.GetLongDouble(&offset);726success = true;727}728}729}730}731}732}733734if (success)735return_valobj_sp = ValueObjectConstResult::Create(736thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));737} else if (type_flags & eTypeIsVector && *byte_size <= 16) {738if (*byte_size > 0) {739const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);740741if (v0_info) {742std::unique_ptr<DataBufferHeap> heap_data_up(743new DataBufferHeap(*byte_size, 0));744const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();745RegisterValue reg_value;746if (reg_ctx->ReadRegister(v0_info, reg_value)) {747Status error;748if (reg_value.GetAsMemoryData(*v0_info, heap_data_up->GetBytes(),749heap_data_up->GetByteSize(), byte_order,750error)) {751DataExtractor data(DataBufferSP(heap_data_up.release()), byte_order,752exe_ctx.GetProcessRef().GetAddressByteSize());753return_valobj_sp = ValueObjectConstResult::Create(754&thread, return_compiler_type, ConstString(""), data);755}756}757}758}759} else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||760(type_flags & eTypeIsVector && *byte_size > 16)) {761DataExtractor data;762763uint32_t NGRN = 0; // Search ABI docs for NGRN764uint32_t NSRN = 0; // Search ABI docs for NSRN765const bool is_return_value = true;766if (LoadValueFromConsecutiveGPRRegisters(767exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN,768data)) {769return_valobj_sp = ValueObjectConstResult::Create(770&thread, return_compiler_type, ConstString(""), data);771}772}773return return_valobj_sp;774}775776lldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) {777if (mask == LLDB_INVALID_ADDRESS_MASK)778return pc;779lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;780return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);781}782783// Reads code or data address mask for the current Linux process.784static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp,785llvm::StringRef reg_name) {786// LLDB_INVALID_ADDRESS_MASK means there isn't a mask or it has not been read787// yet. We do not return the top byte mask unless thread_sp is valid. This788// prevents calls to this function before the thread is setup locking in the789// value to just the top byte mask, in cases where pointer authentication790// might also be active.791uint64_t address_mask = LLDB_INVALID_ADDRESS_MASK;792lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();793if (thread_sp) {794// Linux configures user-space virtual addresses with top byte ignored.795// We set default value of mask such that top byte is masked out.796address_mask = ~((1ULL << 56) - 1);797// If Pointer Authentication feature is enabled then Linux exposes798// PAC data and code mask register. Try reading relevant register799// below and merge it with default address mask calculated above.800lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();801if (reg_ctx_sp) {802const RegisterInfo *reg_info =803reg_ctx_sp->GetRegisterInfoByName(reg_name, 0);804if (reg_info) {805lldb::addr_t mask_reg_val = reg_ctx_sp->ReadRegisterAsUnsigned(806reg_info->kinds[eRegisterKindLLDB], LLDB_INVALID_ADDRESS);807if (mask_reg_val != LLDB_INVALID_ADDRESS)808address_mask |= mask_reg_val;809}810}811}812return address_mask;813}814815lldb::addr_t ABISysV_arm64::FixCodeAddress(lldb::addr_t pc) {816if (lldb::ProcessSP process_sp = GetProcessSP()) {817if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() &&818process_sp->GetCodeAddressMask() == LLDB_INVALID_ADDRESS_MASK)819process_sp->SetCodeAddressMask(820ReadLinuxProcessAddressMask(process_sp, "code_mask"));821822// b55 is the highest bit outside TBI (if it's enabled), use823// it to determine if the high bits are set to 0 or 1.824const addr_t pac_sign_extension = 0x0080000000000000ULL;825addr_t mask = process_sp->GetCodeAddressMask();826// Test if the high memory mask has been overriden separately827if (pc & pac_sign_extension &&828process_sp->GetHighmemCodeAddressMask() != LLDB_INVALID_ADDRESS_MASK)829mask = process_sp->GetHighmemCodeAddressMask();830831return FixAddress(pc, mask);832}833return pc;834}835836lldb::addr_t ABISysV_arm64::FixDataAddress(lldb::addr_t pc) {837if (lldb::ProcessSP process_sp = GetProcessSP()) {838if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() &&839process_sp->GetDataAddressMask() == LLDB_INVALID_ADDRESS_MASK)840process_sp->SetDataAddressMask(841ReadLinuxProcessAddressMask(process_sp, "data_mask"));842843// b55 is the highest bit outside TBI (if it's enabled), use844// it to determine if the high bits are set to 0 or 1.845const addr_t pac_sign_extension = 0x0080000000000000ULL;846addr_t mask = process_sp->GetDataAddressMask();847// Test if the high memory mask has been overriden separately848if (pc & pac_sign_extension &&849process_sp->GetHighmemDataAddressMask() != LLDB_INVALID_ADDRESS_MASK)850mask = process_sp->GetHighmemDataAddressMask();851852return FixAddress(pc, mask);853}854return pc;855}856857void ABISysV_arm64::Initialize() {858PluginManager::RegisterPlugin(GetPluginNameStatic(),859"SysV ABI for AArch64 targets", CreateInstance);860}861862void ABISysV_arm64::Terminate() {863PluginManager::UnregisterPlugin(CreateInstance);864}865866867