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