1 //===-- AArch66.h ---------------------------------------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/lldb-types.h" 10 11 #include "ABIAArch64.h" 12 #ifdef LLDB_ENABLE_ALL 13 #include "ABIMacOSX_arm64.h" 14 #endif // LLDB_ENABLE_ALL 15 #include "ABISysV_arm64.h" 16 #include "Utility/ARM64_DWARF_Registers.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Target/Process.h" 19 20 #include <bitset> 21 #include <optional> 22 23 using namespace lldb; 24 25 LLDB_PLUGIN_DEFINE(ABIAArch64) 26 27 void ABIAArch64::Initialize() { 28 ABISysV_arm64::Initialize(); 29 #ifdef LLDB_ENABLE_ALL 30 ABIMacOSX_arm64::Initialize(); 31 #endif // LLDB_ENABLE_ALL 32 } 33 34 void ABIAArch64::Terminate() { 35 ABISysV_arm64::Terminate(); 36 #ifdef LLDB_ENABLE_ALL 37 ABIMacOSX_arm64::Terminate(); 38 #endif // LLDB_ENABLE_ALL 39 } 40 41 lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) { 42 if (lldb::ProcessSP process_sp = GetProcessSP()) { 43 // b55 is the highest bit outside TBI (if it's enabled), use 44 // it to determine if the high bits are set to 0 or 1. 45 const addr_t pac_sign_extension = 0x0080000000000000ULL; 46 addr_t mask = process_sp->GetCodeAddressMask(); 47 // Test if the high memory mask has been overriden separately 48 if (pc & pac_sign_extension && 49 process_sp->GetHighmemCodeAddressMask() != LLDB_INVALID_ADDRESS_MASK) 50 mask = process_sp->GetHighmemCodeAddressMask(); 51 52 if (mask != LLDB_INVALID_ADDRESS_MASK) 53 return FixAddress(pc, mask); 54 } 55 return pc; 56 } 57 58 lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) { 59 if (lldb::ProcessSP process_sp = GetProcessSP()) { 60 // b55 is the highest bit outside TBI (if it's enabled), use 61 // it to determine if the high bits are set to 0 or 1. 62 const addr_t pac_sign_extension = 0x0080000000000000ULL; 63 addr_t mask = process_sp->GetDataAddressMask(); 64 // Test if the high memory mask has been overriden separately 65 if (pc & pac_sign_extension && 66 process_sp->GetHighmemDataAddressMask() != LLDB_INVALID_ADDRESS_MASK) 67 mask = process_sp->GetHighmemDataAddressMask(); 68 if (mask != LLDB_INVALID_ADDRESS_MASK) 69 return FixAddress(pc, mask); 70 } 71 return pc; 72 } 73 74 std::pair<uint32_t, uint32_t> 75 ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) { 76 if (name == "pc") 77 return {LLDB_INVALID_REGNUM, arm64_dwarf::pc}; 78 if (name == "cpsr") 79 return {LLDB_INVALID_REGNUM, arm64_dwarf::cpsr}; 80 return MCBasedABI::GetEHAndDWARFNums(name); 81 } 82 83 std::string ABIAArch64::GetMCName(std::string reg) { 84 MapRegisterName(reg, "v", "q"); 85 MapRegisterName(reg, "x29", "fp"); 86 MapRegisterName(reg, "x30", "lr"); 87 return reg; 88 } 89 90 uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) { 91 return llvm::StringSwitch<uint32_t>(name) 92 .Case("pc", LLDB_REGNUM_GENERIC_PC) 93 .Cases("lr", "x30", LLDB_REGNUM_GENERIC_RA) 94 .Cases("sp", "x31", LLDB_REGNUM_GENERIC_SP) 95 .Cases("fp", "x29", LLDB_REGNUM_GENERIC_FP) 96 .Case("cpsr", LLDB_REGNUM_GENERIC_FLAGS) 97 .Case("x0", LLDB_REGNUM_GENERIC_ARG1) 98 .Case("x1", LLDB_REGNUM_GENERIC_ARG2) 99 .Case("x2", LLDB_REGNUM_GENERIC_ARG3) 100 .Case("x3", LLDB_REGNUM_GENERIC_ARG4) 101 .Case("x4", LLDB_REGNUM_GENERIC_ARG5) 102 .Case("x5", LLDB_REGNUM_GENERIC_ARG6) 103 .Case("x6", LLDB_REGNUM_GENERIC_ARG7) 104 .Case("x7", LLDB_REGNUM_GENERIC_ARG8) 105 .Default(LLDB_INVALID_REGNUM); 106 } 107 108 static void addPartialRegisters( 109 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s, 110 llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices, 111 uint32_t full_reg_size, const char *partial_reg_format, 112 uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) { 113 for (auto it : llvm::enumerate(full_reg_indices)) { 114 std::optional<uint32_t> full_reg_index = it.value(); 115 if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size) 116 return; 117 118 lldb_private::DynamicRegisterInfo::Register partial_reg{ 119 lldb_private::ConstString( 120 llvm::formatv(partial_reg_format, it.index()).str()), 121 lldb_private::ConstString(), 122 lldb_private::ConstString("supplementary registers"), 123 partial_reg_size, 124 LLDB_INVALID_INDEX32, 125 encoding, 126 format, 127 LLDB_INVALID_REGNUM, 128 LLDB_INVALID_REGNUM, 129 LLDB_INVALID_REGNUM, 130 LLDB_INVALID_REGNUM, 131 {*full_reg_index}, 132 {}}; 133 addSupplementaryRegister(regs, partial_reg); 134 } 135 } 136 137 void ABIAArch64::AugmentRegisterInfo( 138 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) { 139 lldb_private::MCBasedABI::AugmentRegisterInfo(regs); 140 141 lldb_private::ConstString sp_string{"sp"}; 142 143 std::array<std::optional<uint32_t>, 32> x_regs; 144 std::array<std::optional<uint32_t>, 32> v_regs; 145 146 for (auto it : llvm::enumerate(regs)) { 147 lldb_private::DynamicRegisterInfo::Register &info = it.value(); 148 // GDB sends x31 as "sp". Add the "x31" alt_name for convenience. 149 if (info.name == sp_string && !info.alt_name) 150 info.alt_name.SetCString("x31"); 151 152 unsigned int reg_num; 153 auto get_reg = [&info, ®_num](const char *prefix) { 154 llvm::StringRef reg_name = info.name.GetStringRef(); 155 llvm::StringRef alt_name = info.alt_name.GetStringRef(); 156 return (reg_name.consume_front(prefix) && 157 llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) || 158 (alt_name.consume_front(prefix) && 159 llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32); 160 }; 161 162 if (get_reg("x")) 163 x_regs[reg_num] = it.index(); 164 else if (get_reg("v")) 165 v_regs[reg_num] = it.index(); 166 // if we have at least one subregister, abort 167 else if (get_reg("w") || get_reg("s") || get_reg("d")) 168 return; 169 } 170 171 // Create aliases for partial registers: wN for xN, and sN/dN for vN. 172 addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint, 173 lldb::eFormatHex); 174 addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754, 175 lldb::eFormatFloat); 176 addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754, 177 lldb::eFormatFloat); 178 } 179