1214518Srpaulo//===-- ABISysV_arm64.cpp -------------------------------------------------===// 2190214Srpaulo// 3190214Srpaulo// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4190214Srpaulo// See https://llvm.org/LICENSE.txt for license information. 5190214Srpaulo// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6190214Srpaulo// 7190214Srpaulo//===----------------------------------------------------------------------===// 8190214Srpaulo 9190214Srpaulo#include "ABISysV_arm64.h" 10190214Srpaulo 11190214Srpaulo#include <optional> 12190214Srpaulo#include <vector> 13190214Srpaulo 14190214Srpaulo#include "llvm/ADT/STLExtras.h" 15190214Srpaulo#include "llvm/TargetParser/Triple.h" 16190214Srpaulo 17190214Srpaulo#include "lldb/Core/Module.h" 18190214Srpaulo#include "lldb/Core/PluginManager.h" 19190214Srpaulo#include "lldb/Core/Value.h" 20190214Srpaulo#include "lldb/Core/ValueObjectConstResult.h" 21190214Srpaulo#include "lldb/Symbol/UnwindPlan.h" 22190214Srpaulo#include "lldb/Target/Process.h" 23190214Srpaulo#include "lldb/Target/RegisterContext.h" 24190214Srpaulo#include "lldb/Target/Target.h" 25190214Srpaulo#include "lldb/Target/Thread.h" 26190214Srpaulo#include "lldb/Utility/ConstString.h" 27190214Srpaulo#include "lldb/Utility/LLDBLog.h" 28190214Srpaulo#include "lldb/Utility/Log.h" 29190214Srpaulo#include "lldb/Utility/RegisterValue.h" 30190214Srpaulo#include "lldb/Utility/Scalar.h" 31190214Srpaulo#include "lldb/Utility/Status.h" 32190214Srpaulo 33190214Srpaulo#include "Utility/ARM64_DWARF_Registers.h" 34190214Srpaulo 35190214Srpaulousing namespace lldb; 36190214Srpaulousing namespace lldb_private; 37190214Srpaulo 38190214Srpaulobool ABISysV_arm64::GetPointerReturnRegister(const char *&name) { 39190214Srpaulo name = "x0"; 40235426Sdelphij return true; 41235426Sdelphij} 42235426Sdelphij 43235426Sdelphijsize_t ABISysV_arm64::GetRedZoneSize() const { return 128; } 44235426Sdelphij 45235426Sdelphij// Static Functions 46190214Srpaulo 47235426SdelphijABISP 48235426SdelphijABISysV_arm64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { 49235426Sdelphij const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); 50235426Sdelphij const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor(); 51235426Sdelphij 52235426Sdelphij if (vendor_type != llvm::Triple::Apple) { 53235426Sdelphij if (arch_type == llvm::Triple::aarch64 || 54235426Sdelphij arch_type == llvm::Triple::aarch64_32) { 55235426Sdelphij return ABISP( 56235426Sdelphij new ABISysV_arm64(std::move(process_sp), MakeMCRegisterInfo(arch))); 57235426Sdelphij } 58235426Sdelphij } 59235426Sdelphij 60235426Sdelphij return ABISP(); 61235426Sdelphij} 62235426Sdelphij 63235426Sdelphijbool ABISysV_arm64::PrepareTrivialCall(Thread &thread, addr_t sp, 64235426Sdelphij addr_t func_addr, addr_t return_addr, 65235426Sdelphij llvm::ArrayRef<addr_t> args) const { 66235426Sdelphij RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 67235426Sdelphij if (!reg_ctx) 68235426Sdelphij return false; 69235426Sdelphij 70235426Sdelphij Log *log = GetLog(LLDBLog::Expressions); 71235426Sdelphij 72235426Sdelphij if (log) { 73235426Sdelphij StreamString s; 74235426Sdelphij s.Printf("ABISysV_arm64::PrepareTrivialCall (tid = 0x%" PRIx64 75235426Sdelphij ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 76190214Srpaulo ", return_addr = 0x%" PRIx64, 77235426Sdelphij thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, 78190214Srpaulo (uint64_t)return_addr); 79190214Srpaulo 80190214Srpaulo for (size_t i = 0; i < args.size(); ++i) 81190214Srpaulo s.Printf(", arg%d = 0x%" PRIx64, static_cast<int>(i + 1), args[i]); 82190214Srpaulo s.PutCString(")"); 83235426Sdelphij log->PutString(s.GetString()); 84235426Sdelphij } 85190214Srpaulo 86190214Srpaulo // x0 - x7 contain first 8 simple args 87190214Srpaulo if (args.size() > 8) 88190214Srpaulo return false; 89190214Srpaulo 90190214Srpaulo for (size_t i = 0; i < args.size(); ++i) { 91190214Srpaulo const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( 92190214Srpaulo eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); 93190214Srpaulo LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s", 94190214Srpaulo static_cast<int>(i + 1), args[i], reg_info->name); 95190214Srpaulo if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) 96190214Srpaulo return false; 97190214Srpaulo } 98190214Srpaulo 99190214Srpaulo // Set "lr" to the return address 100190214Srpaulo if (!reg_ctx->WriteRegisterFromUnsigned( 101190214Srpaulo reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 102190214Srpaulo LLDB_REGNUM_GENERIC_RA), 103190214Srpaulo return_addr)) 104190214Srpaulo return false; 105190214Srpaulo 106190214Srpaulo // Set "sp" to the requested value 107235426Sdelphij if (!reg_ctx->WriteRegisterFromUnsigned( 108190214Srpaulo reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 109190214Srpaulo LLDB_REGNUM_GENERIC_SP), 110190214Srpaulo sp)) 111190214Srpaulo return false; 112190214Srpaulo 113190214Srpaulo // Set "pc" to the address requested 114190214Srpaulo if (!reg_ctx->WriteRegisterFromUnsigned( 115190214Srpaulo reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 116190214Srpaulo LLDB_REGNUM_GENERIC_PC), 117190214Srpaulo func_addr)) 118190214Srpaulo return false; 119190214Srpaulo 120190214Srpaulo return true; 121190214Srpaulo} 122190214Srpaulo 123190214Srpaulo// TODO: We dont support fp/SIMD arguments in v0-v7 124190214Srpaulobool ABISysV_arm64::GetArgumentValues(Thread &thread, ValueList &values) const { 125190214Srpaulo uint32_t num_values = values.GetSize(); 126190214Srpaulo 127190214Srpaulo ExecutionContext exe_ctx(thread.shared_from_this()); 128190214Srpaulo 129235426Sdelphij // Extract the register context so we can read arguments from registers 130190214Srpaulo 131190214Srpaulo RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 132190214Srpaulo 133190214Srpaulo if (!reg_ctx) 134190214Srpaulo return false; 135190214Srpaulo 136190214Srpaulo addr_t sp = 0; 137190214Srpaulo 138190214Srpaulo for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) { 139190214Srpaulo // We currently only support extracting values with Clang QualTypes. Do we 140190214Srpaulo // care about others? 141190214Srpaulo Value *value = values.GetValueAtIndex(value_idx); 142190214Srpaulo 143190214Srpaulo if (!value) 144190214Srpaulo return false; 145190214Srpaulo 146190214Srpaulo CompilerType value_type = value->GetCompilerType(); 147190214Srpaulo if (value_type) { 148190214Srpaulo bool is_signed = false; 149190214Srpaulo size_t bit_width = 0; 150235426Sdelphij std::optional<uint64_t> bit_size = value_type.GetBitSize(&thread); 151190214Srpaulo if (!bit_size) 152235426Sdelphij return false; 153190214Srpaulo if (value_type.IsIntegerOrEnumerationType(is_signed)) { 154190214Srpaulo bit_width = *bit_size; 155190214Srpaulo } else if (value_type.IsPointerOrReferenceType()) { 156190214Srpaulo bit_width = *bit_size; 157190214Srpaulo } else { 158190214Srpaulo // We only handle integer, pointer and reference types currently... 159190214Srpaulo return false; 160190214Srpaulo } 161190214Srpaulo 162190214Srpaulo if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) { 163190214Srpaulo if (value_idx < 8) { 164190214Srpaulo // Arguments 1-8 are in x0-x7... 165190214Srpaulo const RegisterInfo *reg_info = nullptr; 166190214Srpaulo reg_info = reg_ctx->GetRegisterInfo( 167190214Srpaulo eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); 168190214Srpaulo 169190214Srpaulo if (reg_info) { 170190214Srpaulo RegisterValue reg_value; 171190214Srpaulo 172190214Srpaulo if (reg_ctx->ReadRegister(reg_info, reg_value)) { 173190214Srpaulo if (is_signed) 174190214Srpaulo reg_value.SignExtend(bit_width); 175190214Srpaulo if (!reg_value.GetScalarValue(value->GetScalar())) 176190214Srpaulo return false; 177190214Srpaulo continue; 178190214Srpaulo } 179190214Srpaulo } 180190214Srpaulo return false; 181190214Srpaulo } else { 182190214Srpaulo // TODO: Verify for stack layout for SysV 183190214Srpaulo if (sp == 0) { 184190214Srpaulo // Read the stack pointer if we already haven't read it 185190214Srpaulo sp = reg_ctx->GetSP(0); 186190214Srpaulo if (sp == 0) 187190214Srpaulo return false; 188190214Srpaulo } 189190214Srpaulo 190190214Srpaulo // Arguments 5 on up are on the stack 191190214Srpaulo const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8; 192190214Srpaulo Status error; 193190214Srpaulo if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory( 194235426Sdelphij sp, arg_byte_size, is_signed, value->GetScalar(), error)) 195190214Srpaulo return false; 196190214Srpaulo 197190214Srpaulo sp += arg_byte_size; 198190214Srpaulo // Align up to the next 8 byte boundary if needed 199190214Srpaulo if (sp % 8) { 200190214Srpaulo sp >>= 3; 201190214Srpaulo sp += 1; 202190214Srpaulo sp <<= 3; 203190214Srpaulo } 204190214Srpaulo } 205190214Srpaulo } 206190214Srpaulo } 207235426Sdelphij } 208235426Sdelphij return true; 209235426Sdelphij} 210235426Sdelphij 211235426SdelphijStatus ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, 212235426Sdelphij lldb::ValueObjectSP &new_value_sp) { 213235426Sdelphij Status error; 214235426Sdelphij if (!new_value_sp) { 215235426Sdelphij error.SetErrorString("Empty value object for return value."); 216235426Sdelphij return error; 217235426Sdelphij } 218190214Srpaulo 219190214Srpaulo CompilerType return_value_type = new_value_sp->GetCompilerType(); 220190214Srpaulo if (!return_value_type) { 221190214Srpaulo error.SetErrorString("Null clang type for return value."); 222190214Srpaulo return error; 223190214Srpaulo } 224190214Srpaulo 225190214Srpaulo Thread *thread = frame_sp->GetThread().get(); 226190214Srpaulo 227190214Srpaulo RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 228190214Srpaulo 229190214Srpaulo if (reg_ctx) { 230190214Srpaulo DataExtractor data; 231190214Srpaulo Status data_error; 232190214Srpaulo const uint64_t byte_size = new_value_sp->GetData(data, data_error); 233190214Srpaulo if (data_error.Fail()) { 234190214Srpaulo error.SetErrorStringWithFormat( 235190214Srpaulo "Couldn't convert return value to raw data: %s", 236190214Srpaulo data_error.AsCString()); 237190214Srpaulo return error; 238190214Srpaulo } 239190214Srpaulo 240190214Srpaulo const uint32_t type_flags = return_value_type.GetTypeInfo(nullptr); 241190214Srpaulo if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { 242190214Srpaulo if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) { 243190214Srpaulo // Extract the register context so we can read arguments from registers 244190214Srpaulo lldb::offset_t offset = 0; 245190214Srpaulo if (byte_size <= 16) { 246190214Srpaulo const RegisterInfo *x0_info = reg_ctx->GetRegisterInfo( 247190214Srpaulo eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); 248190214Srpaulo if (byte_size <= 8) { 249190214Srpaulo uint64_t raw_value = data.GetMaxU64(&offset, byte_size); 250190214Srpaulo 251190214Srpaulo if (!reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value)) 252190214Srpaulo error.SetErrorString("failed to write register x0"); 253190214Srpaulo } else { 254190214Srpaulo uint64_t raw_value = data.GetMaxU64(&offset, 8); 255190214Srpaulo 256190214Srpaulo if (reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value)) { 257190214Srpaulo const RegisterInfo *x1_info = reg_ctx->GetRegisterInfo( 258190214Srpaulo eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); 259190214Srpaulo raw_value = data.GetMaxU64(&offset, byte_size - offset); 260190214Srpaulo 261190214Srpaulo if (!reg_ctx->WriteRegisterFromUnsigned(x1_info, raw_value)) 262190214Srpaulo error.SetErrorString("failed to write register x1"); 263190214Srpaulo } 264190214Srpaulo } 265190214Srpaulo } else { 266190214Srpaulo error.SetErrorString("We don't support returning longer than 128 bit " 267190214Srpaulo "integer values at present."); 268190214Srpaulo } 269190214Srpaulo } else if (type_flags & eTypeIsFloat) { 270190214Srpaulo if (type_flags & eTypeIsComplex) { 271190214Srpaulo // Don't handle complex yet. 272190214Srpaulo error.SetErrorString( 273190214Srpaulo "returning complex float values are not supported"); 274190214Srpaulo } else { 275190214Srpaulo const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0); 276190214Srpaulo 277190214Srpaulo if (v0_info) { 278190214Srpaulo if (byte_size <= 16) { 279190214Srpaulo RegisterValue reg_value; 280190214Srpaulo error = reg_value.SetValueFromData(*v0_info, data, 0, true); 281190214Srpaulo if (error.Success()) 282190214Srpaulo if (!reg_ctx->WriteRegister(v0_info, reg_value)) 283190214Srpaulo error.SetErrorString("failed to write register v0"); 284190214Srpaulo } else { 285190214Srpaulo error.SetErrorString("returning float values longer than 128 " 286190214Srpaulo "bits are not supported"); 287190214Srpaulo } 288190214Srpaulo } else 289190214Srpaulo error.SetErrorString("v0 register is not available on this target"); 290190214Srpaulo } 291190214Srpaulo } 292190214Srpaulo } else if (type_flags & eTypeIsVector) { 293190214Srpaulo if (byte_size > 0) { 294190214Srpaulo const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0); 295190214Srpaulo 296190214Srpaulo if (v0_info) { 297190214Srpaulo if (byte_size <= v0_info->byte_size) { 298190214Srpaulo RegisterValue reg_value; 299190214Srpaulo error = reg_value.SetValueFromData(*v0_info, data, 0, true); 300190214Srpaulo if (error.Success()) { 301190214Srpaulo if (!reg_ctx->WriteRegister(v0_info, reg_value)) 302235426Sdelphij error.SetErrorString("failed to write register v0"); 303235426Sdelphij } 304235426Sdelphij } 305235426Sdelphij } 306235426Sdelphij } 307235426Sdelphij } 308235426Sdelphij } else { 309235426Sdelphij error.SetErrorString("no registers are available"); 310235426Sdelphij } 311190214Srpaulo 312235426Sdelphij return error; 313235426Sdelphij} 314235426Sdelphij 315235426Sdelphijbool ABISysV_arm64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 316235426Sdelphij unwind_plan.Clear(); 317235426Sdelphij unwind_plan.SetRegisterKind(eRegisterKindDWARF); 318235426Sdelphij 319235426Sdelphij uint32_t lr_reg_num = arm64_dwarf::lr; 320235426Sdelphij uint32_t sp_reg_num = arm64_dwarf::sp; 321235426Sdelphij 322235426Sdelphij UnwindPlan::RowSP row(new UnwindPlan::Row); 323235426Sdelphij 324235426Sdelphij // Our previous Call Frame Address is the stack pointer 325235426Sdelphij row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0); 326235426Sdelphij 327235426Sdelphij unwind_plan.AppendRow(row); 328235426Sdelphij unwind_plan.SetReturnAddressRegister(lr_reg_num); 329235426Sdelphij 330235426Sdelphij // All other registers are the same. 331235426Sdelphij 332235426Sdelphij unwind_plan.SetSourceName("arm64 at-func-entry default"); 333235426Sdelphij unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 334235426Sdelphij unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 335235426Sdelphij unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 336235426Sdelphij 337235426Sdelphij return true; 338235426Sdelphij} 339235426Sdelphij 340235426Sdelphijbool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 341235426Sdelphij unwind_plan.Clear(); 342235426Sdelphij unwind_plan.SetRegisterKind(eRegisterKindDWARF); 343235426Sdelphij 344235426Sdelphij uint32_t fp_reg_num = arm64_dwarf::fp; 345235426Sdelphij uint32_t pc_reg_num = arm64_dwarf::pc; 346235426Sdelphij 347235426Sdelphij UnwindPlan::RowSP row(new UnwindPlan::Row); 348235426Sdelphij const int32_t ptr_size = 8; 349235426Sdelphij 350235426Sdelphij row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); 351235426Sdelphij row->SetOffset(0); 352235426Sdelphij row->SetUnspecifiedRegistersAreUndefined(true); 353235426Sdelphij 354235426Sdelphij row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 355235426Sdelphij row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); 356235426Sdelphij 357235426Sdelphij unwind_plan.AppendRow(row); 358235426Sdelphij unwind_plan.SetSourceName("arm64 default unwind plan"); 359235426Sdelphij unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 360235426Sdelphij unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 361235426Sdelphij unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 362235426Sdelphij 363235426Sdelphij return true; 364235426Sdelphij} 365235426Sdelphij 366235426Sdelphij// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says 367235426Sdelphij// registers x19 through x28 and sp are callee preserved. v8-v15 are non- 368235426Sdelphij// volatile (and specifically only the lower 8 bytes of these regs), the rest 369235426Sdelphij// of the fp/SIMD registers are volatile. 370235426Sdelphij 371235426Sdelphij// We treat x29 as callee preserved also, else the unwinder won't try to 372235426Sdelphij// retrieve fp saves. 373235426Sdelphij 374235426Sdelphijbool ABISysV_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) { 375235426Sdelphij if (reg_info) { 376235426Sdelphij const char *name = reg_info->name; 377235426Sdelphij 378235426Sdelphij // Sometimes we'll be called with the "alternate" name for these registers; 379235426Sdelphij // recognize them as non-volatile. 380235426Sdelphij 381235426Sdelphij if (name[0] == 'p' && name[1] == 'c') // pc 382235426Sdelphij return false; 383235426Sdelphij if (name[0] == 'f' && name[1] == 'p') // fp 384235426Sdelphij return false; 385235426Sdelphij if (name[0] == 's' && name[1] == 'p') // sp 386235426Sdelphij return false; 387235426Sdelphij if (name[0] == 'l' && name[1] == 'r') // lr 388235426Sdelphij return false; 389235426Sdelphij 390235426Sdelphij if (name[0] == 'x' || name[0] == 'r') { 391235426Sdelphij // Volatile registers: x0-x18 392235426Sdelphij // Although documentation says only x19-28 + sp are callee saved We ll 393235426Sdelphij // also have to treat x30 as non-volatile. Each dwarf frame has its own 394235426Sdelphij // value of lr. Return false for the non-volatile gpr regs, true for 395235426Sdelphij // everything else 396235426Sdelphij switch (name[1]) { 397235426Sdelphij case '1': 398235426Sdelphij switch (name[2]) { 399235426Sdelphij case '9': 400235426Sdelphij return false; // x19 is non-volatile 401235426Sdelphij default: 402235426Sdelphij return true; 403235426Sdelphij } 404235426Sdelphij break; 405235426Sdelphij case '2': 406235426Sdelphij switch (name[2]) { 407235426Sdelphij case '0': 408235426Sdelphij case '1': 409235426Sdelphij case '2': 410235426Sdelphij case '3': 411235426Sdelphij case '4': 412235426Sdelphij case '5': 413235426Sdelphij case '6': 414235426Sdelphij case '7': 415235426Sdelphij case '8': 416235426Sdelphij return false; // x20 - 28 are non-volatile 417235426Sdelphij case '9': 418235426Sdelphij return false; // x29 aka fp treat as non-volatile 419235426Sdelphij default: 420235426Sdelphij return true; 421235426Sdelphij } 422235426Sdelphij case '3': // x30 (lr) and x31 (sp) treat as non-volatile 423235426Sdelphij if (name[2] == '0' || name[2] == '1') 424235426Sdelphij return false; 425235426Sdelphij break; 426235426Sdelphij default: 427235426Sdelphij return true; // all volatile cases not handled above fall here. 428235426Sdelphij } 429235426Sdelphij } else if (name[0] == 'v' || name[0] == 's' || name[0] == 'd') { 430235426Sdelphij // Volatile registers: v0-7, v16-v31 431235426Sdelphij // Return false for non-volatile fp/SIMD regs, true for everything else 432235426Sdelphij switch (name[1]) { 433235426Sdelphij case '8': 434235426Sdelphij case '9': 435235426Sdelphij return false; // v8-v9 are non-volatile 436235426Sdelphij case '1': 437235426Sdelphij switch (name[2]) { 438235426Sdelphij case '0': 439235426Sdelphij case '1': 440235426Sdelphij case '2': 441235426Sdelphij case '3': 442235426Sdelphij case '4': 443235426Sdelphij case '5': 444235426Sdelphij return false; // v10-v15 are non-volatile 445235426Sdelphij default: 446235426Sdelphij return true; 447235426Sdelphij } 448235426Sdelphij default: 449235426Sdelphij return true; 450235426Sdelphij } 451235426Sdelphij } 452235426Sdelphij } 453235426Sdelphij return true; 454235426Sdelphij} 455235426Sdelphij 456235426Sdelphijstatic bool LoadValueFromConsecutiveGPRRegisters( 457235426Sdelphij ExecutionContext &exe_ctx, RegisterContext *reg_ctx, 458235426Sdelphij const CompilerType &value_type, 459235426Sdelphij bool is_return_value, // false => parameter, true => return value 460235426Sdelphij uint32_t &NGRN, // NGRN (see ABI documentation) 461235426Sdelphij uint32_t &NSRN, // NSRN (see ABI documentation) 462235426Sdelphij DataExtractor &data) { 463235426Sdelphij std::optional<uint64_t> byte_size = 464235426Sdelphij value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); 465235426Sdelphij 466235426Sdelphij if (byte_size || *byte_size == 0) 467235426Sdelphij return false; 468235426Sdelphij 469235426Sdelphij std::unique_ptr<DataBufferHeap> heap_data_up( 470235426Sdelphij new DataBufferHeap(*byte_size, 0)); 471235426Sdelphij const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder(); 472235426Sdelphij Status error; 473235426Sdelphij 474235426Sdelphij CompilerType base_type; 475190214Srpaulo const uint32_t homogeneous_count = 476235426Sdelphij value_type.IsHomogeneousAggregate(&base_type); 477190214Srpaulo if (homogeneous_count > 0 && homogeneous_count <= 8) { 478235426Sdelphij // Make sure we have enough registers 479190214Srpaulo if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) { 480190214Srpaulo if (!base_type) 481235426Sdelphij return false; 482190214Srpaulo std::optional<uint64_t> base_byte_size = 483235426Sdelphij base_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); 484190214Srpaulo if (!base_byte_size) 485190214Srpaulo return false; 486235426Sdelphij uint32_t data_offset = 0; 487190214Srpaulo 488235426Sdelphij for (uint32_t i = 0; i < homogeneous_count; ++i) { 489190214Srpaulo char v_name[8]; 490190214Srpaulo ::snprintf(v_name, sizeof(v_name), "v%u", NSRN); 491190214Srpaulo const RegisterInfo *reg_info = 492190214Srpaulo reg_ctx->GetRegisterInfoByName(v_name, 0); 493190214Srpaulo if (reg_info == nullptr) 494190214Srpaulo return false; 495190214Srpaulo 496190214Srpaulo if (*base_byte_size > reg_info->byte_size) 497190214Srpaulo return false; 498190214Srpaulo 499190214Srpaulo RegisterValue reg_value; 500190214Srpaulo 501190214Srpaulo if (!reg_ctx->ReadRegister(reg_info, reg_value)) 502190214Srpaulo return false; 503190214Srpaulo 504190214Srpaulo // Make sure we have enough room in "heap_data_up" 505190214Srpaulo if ((data_offset + *base_byte_size) <= heap_data_up->GetByteSize()) { 506190214Srpaulo const size_t bytes_copied = reg_value.GetAsMemoryData( 507190214Srpaulo *reg_info, heap_data_up->GetBytes() + data_offset, 508190214Srpaulo *base_byte_size, byte_order, error); 509190214Srpaulo if (bytes_copied != *base_byte_size) 510190214Srpaulo return false; 511190214Srpaulo data_offset += bytes_copied; 512190214Srpaulo ++NSRN; 513235426Sdelphij } else 514190214Srpaulo return false; 515235426Sdelphij } 516190214Srpaulo data.SetByteOrder(byte_order); 517190214Srpaulo data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize()); 518190214Srpaulo data.SetData(DataBufferSP(heap_data_up.release())); 519190214Srpaulo return true; 520190214Srpaulo } 521190214Srpaulo } 522190214Srpaulo 523190214Srpaulo const size_t max_reg_byte_size = 16; 524190214Srpaulo if (*byte_size <= max_reg_byte_size) { 525190214Srpaulo size_t bytes_left = *byte_size; 526190214Srpaulo uint32_t data_offset = 0; 527190214Srpaulo while (data_offset < *byte_size) { 528190214Srpaulo if (NGRN >= 8) 529190214Srpaulo return false; 530190214Srpaulo 531190214Srpaulo const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( 532235426Sdelphij eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN); 533190214Srpaulo if (reg_info == nullptr) 534190214Srpaulo return false; 535190214Srpaulo 536190214Srpaulo RegisterValue reg_value; 537235426Sdelphij 538190214Srpaulo if (!reg_ctx->ReadRegister(reg_info, reg_value)) 539235426Sdelphij return false; 540190214Srpaulo 541235426Sdelphij const size_t curr_byte_size = std::min<size_t>(8, bytes_left); 542235426Sdelphij const size_t bytes_copied = reg_value.GetAsMemoryData( 543235426Sdelphij *reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size, 544235426Sdelphij byte_order, error); 545235426Sdelphij if (bytes_copied == 0) 546235426Sdelphij return false; 547235426Sdelphij if (bytes_copied >= bytes_left) 548235426Sdelphij break; 549235426Sdelphij data_offset += bytes_copied; 550235426Sdelphij bytes_left -= bytes_copied; 551235426Sdelphij ++NGRN; 552235426Sdelphij } 553235426Sdelphij } else { 554235426Sdelphij const RegisterInfo *reg_info = nullptr; 555235426Sdelphij if (is_return_value) { 556235426Sdelphij // The SysV arm64 ABI doesn't require you to write the return location 557235426Sdelphij // back to x8 before returning from the function the way the x86_64 ABI 558235426Sdelphij // does. It looks like all the users of this ABI currently choose not to 559235426Sdelphij // do that, and so we can't reconstruct stack based returns on exit 560235426Sdelphij // from the function. 561235426Sdelphij return false; 562235426Sdelphij } else { 563235426Sdelphij // We are assuming we are stopped at the first instruction in a function 564235426Sdelphij // and that the ABI is being respected so all parameters appear where 565235426Sdelphij // they should be (functions with no external linkage can legally violate 566235426Sdelphij // the ABI). 567235426Sdelphij if (NGRN >= 8) 568235426Sdelphij return false; 569235426Sdelphij 570235426Sdelphij reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 571235426Sdelphij LLDB_REGNUM_GENERIC_ARG1 + NGRN); 572235426Sdelphij if (reg_info == nullptr) 573235426Sdelphij return false; 574235426Sdelphij ++NGRN; 575235426Sdelphij } 576235426Sdelphij 577235426Sdelphij const lldb::addr_t value_addr = 578235426Sdelphij reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS); 579235426Sdelphij 580235426Sdelphij if (value_addr == LLDB_INVALID_ADDRESS) 581235426Sdelphij return false; 582235426Sdelphij 583235426Sdelphij if (exe_ctx.GetProcessRef().ReadMemory( 584235426Sdelphij value_addr, heap_data_up->GetBytes(), heap_data_up->GetByteSize(), 585235426Sdelphij error) != heap_data_up->GetByteSize()) { 586235426Sdelphij return false; 587235426Sdelphij } 588235426Sdelphij } 589235426Sdelphij 590235426Sdelphij data.SetByteOrder(byte_order); 591235426Sdelphij data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize()); 592235426Sdelphij data.SetData(DataBufferSP(heap_data_up.release())); 593235426Sdelphij return true; 594235426Sdelphij} 595235426Sdelphij 596235426SdelphijValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl( 597235426Sdelphij Thread &thread, CompilerType &return_compiler_type) const { 598235426Sdelphij ValueObjectSP return_valobj_sp; 599235426Sdelphij Value value; 600235426Sdelphij 601235426Sdelphij ExecutionContext exe_ctx(thread.shared_from_this()); 602235426Sdelphij if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr) 603235426Sdelphij return return_valobj_sp; 604235426Sdelphij 605235426Sdelphij // value.SetContext (Value::eContextTypeClangType, return_compiler_type); 606235426Sdelphij value.SetCompilerType(return_compiler_type); 607235426Sdelphij 608235426Sdelphij RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 609235426Sdelphij if (!reg_ctx) 610235426Sdelphij return return_valobj_sp; 611235426Sdelphij 612235426Sdelphij std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); 613235426Sdelphij if (!byte_size) 614235426Sdelphij return return_valobj_sp; 615235426Sdelphij 616235426Sdelphij const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); 617235426Sdelphij if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { 618235426Sdelphij value.SetValueType(Value::ValueType::Scalar); 619235426Sdelphij 620235426Sdelphij bool success = false; 621235426Sdelphij if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) { 622235426Sdelphij // Extract the register context so we can read arguments from registers 623235426Sdelphij if (*byte_size <= 8) { 624235426Sdelphij const RegisterInfo *x0_reg_info = nullptr; 625235426Sdelphij x0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 626235426Sdelphij LLDB_REGNUM_GENERIC_ARG1); 627235426Sdelphij if (x0_reg_info) { 628235426Sdelphij uint64_t raw_value = 629235426Sdelphij thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info, 630235426Sdelphij 0); 631235426Sdelphij const bool is_signed = (type_flags & eTypeIsSigned) != 0; 632235426Sdelphij switch (*byte_size) { 633235426Sdelphij default: 634235426Sdelphij break; 635235426Sdelphij case 16: // uint128_t 636235426Sdelphij // In register x0 and x1 637235426Sdelphij { 638235426Sdelphij const RegisterInfo *x1_reg_info = nullptr; 639235426Sdelphij x1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, 640235426Sdelphij LLDB_REGNUM_GENERIC_ARG2); 641235426Sdelphij 642235426Sdelphij if (x1_reg_info) { 643235426Sdelphij if (*byte_size <= 644235426Sdelphij x0_reg_info->byte_size + x1_reg_info->byte_size) { 645235426Sdelphij std::unique_ptr<DataBufferHeap> heap_data_up( 646235426Sdelphij new DataBufferHeap(*byte_size, 0)); 647235426Sdelphij const ByteOrder byte_order = 648235426Sdelphij exe_ctx.GetProcessRef().GetByteOrder(); 649235426Sdelphij RegisterValue x0_reg_value; 650235426Sdelphij RegisterValue x1_reg_value; 651235426Sdelphij if (reg_ctx->ReadRegister(x0_reg_info, x0_reg_value) && 652235426Sdelphij reg_ctx->ReadRegister(x1_reg_info, x1_reg_value)) { 653235426Sdelphij Status error; 654235426Sdelphij if (x0_reg_value.GetAsMemoryData( 655235426Sdelphij *x0_reg_info, heap_data_up->GetBytes() + 0, 8, 656235426Sdelphij byte_order, error) && 657235426Sdelphij x1_reg_value.GetAsMemoryData( 658235426Sdelphij *x1_reg_info, heap_data_up->GetBytes() + 8, 8, 659235426Sdelphij byte_order, error)) { 660235426Sdelphij DataExtractor data( 661235426Sdelphij DataBufferSP(heap_data_up.release()), byte_order, 662235426Sdelphij exe_ctx.GetProcessRef().GetAddressByteSize()); 663235426Sdelphij 664235426Sdelphij return_valobj_sp = ValueObjectConstResult::Create( 665235426Sdelphij &thread, return_compiler_type, ConstString(""), data); 666235426Sdelphij return return_valobj_sp; 667235426Sdelphij } 668235426Sdelphij } 669235426Sdelphij } 670235426Sdelphij } 671235426Sdelphij } 672235426Sdelphij break; 673235426Sdelphij case sizeof(uint64_t): 674235426Sdelphij if (is_signed) 675235426Sdelphij value.GetScalar() = (int64_t)(raw_value); 676235426Sdelphij else 677235426Sdelphij value.GetScalar() = (uint64_t)(raw_value); 678235426Sdelphij success = true; 679235426Sdelphij break; 680235426Sdelphij 681235426Sdelphij case sizeof(uint32_t): 682235426Sdelphij if (is_signed) 683235426Sdelphij value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); 684235426Sdelphij else 685235426Sdelphij value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); 686235426Sdelphij success = true; 687235426Sdelphij break; 688235426Sdelphij 689235426Sdelphij case sizeof(uint16_t): 690235426Sdelphij if (is_signed) 691235426Sdelphij value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); 692235426Sdelphij else 693235426Sdelphij value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); 694235426Sdelphij success = true; 695235426Sdelphij break; 696235426Sdelphij 697235426Sdelphij case sizeof(uint8_t): 698235426Sdelphij if (is_signed) 699235426Sdelphij value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); 700235426Sdelphij else 701235426Sdelphij value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); 702235426Sdelphij success = true; 703235426Sdelphij break; 704235426Sdelphij } 705235426Sdelphij } 706235426Sdelphij } 707235426Sdelphij } else if (type_flags & eTypeIsFloat) { 708235426Sdelphij if (type_flags & eTypeIsComplex) { 709235426Sdelphij // Don't handle complex yet. 710235426Sdelphij } else { 711235426Sdelphij if (*byte_size <= sizeof(long double)) { 712235426Sdelphij const RegisterInfo *v0_reg_info = 713235426Sdelphij reg_ctx->GetRegisterInfoByName("v0", 0); 714235426Sdelphij RegisterValue v0_value; 715235426Sdelphij if (reg_ctx->ReadRegister(v0_reg_info, v0_value)) { 716235426Sdelphij DataExtractor data; 717235426Sdelphij if (v0_value.GetData(data)) { 718235426Sdelphij lldb::offset_t offset = 0; 719235426Sdelphij if (*byte_size == sizeof(float)) { 720235426Sdelphij value.GetScalar() = data.GetFloat(&offset); 721235426Sdelphij success = true; 722235426Sdelphij } else if (*byte_size == sizeof(double)) { 723235426Sdelphij value.GetScalar() = data.GetDouble(&offset); 724235426Sdelphij success = true; 725235426Sdelphij } else if (*byte_size == sizeof(long double)) { 726235426Sdelphij value.GetScalar() = data.GetLongDouble(&offset); 727235426Sdelphij success = true; 728235426Sdelphij } 729235426Sdelphij } 730235426Sdelphij } 731235426Sdelphij } 732235426Sdelphij } 733235426Sdelphij } 734235426Sdelphij 735235426Sdelphij if (success) 736235426Sdelphij return_valobj_sp = ValueObjectConstResult::Create( 737235426Sdelphij thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); 738235426Sdelphij } else if (type_flags & eTypeIsVector && *byte_size <= 16) { 739235426Sdelphij if (*byte_size > 0) { 740235426Sdelphij const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0); 741235426Sdelphij 742235426Sdelphij if (v0_info) { 743235426Sdelphij std::unique_ptr<DataBufferHeap> heap_data_up( 744235426Sdelphij new DataBufferHeap(*byte_size, 0)); 745235426Sdelphij const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder(); 746235426Sdelphij RegisterValue reg_value; 747235426Sdelphij if (reg_ctx->ReadRegister(v0_info, reg_value)) { 748235426Sdelphij Status error; 749235426Sdelphij if (reg_value.GetAsMemoryData(*v0_info, heap_data_up->GetBytes(), 750235426Sdelphij heap_data_up->GetByteSize(), byte_order, 751235426Sdelphij error)) { 752235426Sdelphij DataExtractor data(DataBufferSP(heap_data_up.release()), byte_order, 753235426Sdelphij exe_ctx.GetProcessRef().GetAddressByteSize()); 754235426Sdelphij return_valobj_sp = ValueObjectConstResult::Create( 755235426Sdelphij &thread, return_compiler_type, ConstString(""), data); 756235426Sdelphij } 757235426Sdelphij } 758235426Sdelphij } 759235426Sdelphij } 760235426Sdelphij } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass || 761235426Sdelphij (type_flags & eTypeIsVector && *byte_size > 16)) { 762235426Sdelphij DataExtractor data; 763235426Sdelphij 764235426Sdelphij uint32_t NGRN = 0; // Search ABI docs for NGRN 765235426Sdelphij uint32_t NSRN = 0; // Search ABI docs for NSRN 766235426Sdelphij const bool is_return_value = true; 767235426Sdelphij if (LoadValueFromConsecutiveGPRRegisters( 768235426Sdelphij exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, 769235426Sdelphij data)) { 770235426Sdelphij return_valobj_sp = ValueObjectConstResult::Create( 771235426Sdelphij &thread, return_compiler_type, ConstString(""), data); 772235426Sdelphij } 773235426Sdelphij } 774235426Sdelphij return return_valobj_sp; 775235426Sdelphij} 776235426Sdelphij 777235426Sdelphijlldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) { 778235426Sdelphij lldb::addr_t pac_sign_extension = 0x0080000000000000ULL; 779235426Sdelphij return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); 780235426Sdelphij} 781235426Sdelphij 782235426Sdelphij// Reads code or data address mask for the current Linux process. 783235426Sdelphijstatic lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp, 784235426Sdelphij llvm::StringRef reg_name) { 785235426Sdelphij // 0 means there isn't a mask or it has not been read yet. 786235426Sdelphij // We do not return the top byte mask unless thread_sp is valid. 787235426Sdelphij // This prevents calls to this function before the thread is setup locking 788235426Sdelphij // in the value to just the top byte mask, in cases where pointer 789235426Sdelphij // authentication might also be active. 790235426Sdelphij uint64_t address_mask = 0; 791235426Sdelphij lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); 792235426Sdelphij if (thread_sp) { 793235426Sdelphij // Linux configures user-space virtual addresses with top byte ignored. 794235426Sdelphij // We set default value of mask such that top byte is masked out. 795235426Sdelphij address_mask = ~((1ULL << 56) - 1); 796235426Sdelphij // If Pointer Authentication feature is enabled then Linux exposes 797235426Sdelphij // PAC data and code mask register. Try reading relevant register 798235426Sdelphij // below and merge it with default address mask calculated above. 799235426Sdelphij lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); 800235426Sdelphij if (reg_ctx_sp) { 801235426Sdelphij const RegisterInfo *reg_info = 802235426Sdelphij reg_ctx_sp->GetRegisterInfoByName(reg_name, 0); 803235426Sdelphij if (reg_info) { 804235426Sdelphij lldb::addr_t mask_reg_val = reg_ctx_sp->ReadRegisterAsUnsigned( 805235426Sdelphij reg_info->kinds[eRegisterKindLLDB], LLDB_INVALID_ADDRESS); 806235426Sdelphij if (mask_reg_val != LLDB_INVALID_ADDRESS) 807235426Sdelphij address_mask |= mask_reg_val; 808235426Sdelphij } 809235426Sdelphij } 810235426Sdelphij } 811235426Sdelphij return address_mask; 812235426Sdelphij} 813235426Sdelphij 814235426Sdelphijlldb::addr_t ABISysV_arm64::FixCodeAddress(lldb::addr_t pc) { 815235426Sdelphij if (lldb::ProcessSP process_sp = GetProcessSP()) { 816235426Sdelphij if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() && 817235426Sdelphij !process_sp->GetCodeAddressMask()) 818235426Sdelphij process_sp->SetCodeAddressMask( 819235426Sdelphij ReadLinuxProcessAddressMask(process_sp, "code_mask")); 820235426Sdelphij 821235426Sdelphij return FixAddress(pc, process_sp->GetCodeAddressMask()); 822235426Sdelphij } 823235426Sdelphij return pc; 824235426Sdelphij} 825235426Sdelphij 826235426Sdelphijlldb::addr_t ABISysV_arm64::FixDataAddress(lldb::addr_t pc) { 827235426Sdelphij if (lldb::ProcessSP process_sp = GetProcessSP()) { 828235426Sdelphij if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() && 829235426Sdelphij !process_sp->GetDataAddressMask()) 830235426Sdelphij process_sp->SetDataAddressMask( 831235426Sdelphij ReadLinuxProcessAddressMask(process_sp, "data_mask")); 832190214Srpaulo 833190214Srpaulo return FixAddress(pc, process_sp->GetDataAddressMask()); 834190214Srpaulo } 835190214Srpaulo return pc; 836190214Srpaulo} 837190214Srpaulo 838190214Srpaulovoid ABISysV_arm64::Initialize() { 839190214Srpaulo PluginManager::RegisterPlugin(GetPluginNameStatic(), 840190214Srpaulo "SysV ABI for AArch64 targets", CreateInstance); 841190214Srpaulo} 842190214Srpaulo 843190214Srpaulovoid ABISysV_arm64::Terminate() { 844190214Srpaulo PluginManager::UnregisterPlugin(CreateInstance); 845190214Srpaulo} 846235426Sdelphij