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 #include <optional>
20
LLDB_PLUGIN_DEFINE(ABIAArch64)21 LLDB_PLUGIN_DEFINE(ABIAArch64)
22
23 void ABIAArch64::Initialize() {
24 ABISysV_arm64::Initialize();
25 #ifdef LLDB_ENABLE_ALL
26 ABIMacOSX_arm64::Initialize();
27 #endif // LLDB_ENABLE_ALL
28 }
29
Terminate()30 void ABIAArch64::Terminate() {
31 ABISysV_arm64::Terminate();
32 #ifdef LLDB_ENABLE_ALL
33 ABIMacOSX_arm64::Terminate();
34 #endif // LLDB_ENABLE_ALL
35 }
36
FixCodeAddress(lldb::addr_t pc)37 lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) {
38 if (lldb::ProcessSP process_sp = GetProcessSP())
39 return FixAddress(pc, process_sp->GetCodeAddressMask());
40 return pc;
41 }
42
FixDataAddress(lldb::addr_t pc)43 lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) {
44 if (lldb::ProcessSP process_sp = GetProcessSP())
45 return FixAddress(pc, process_sp->GetDataAddressMask());
46 return pc;
47 }
48
49 std::pair<uint32_t, uint32_t>
GetEHAndDWARFNums(llvm::StringRef name)50 ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {
51 if (name == "pc")
52 return {LLDB_INVALID_REGNUM, arm64_dwarf::pc};
53 if (name == "cpsr")
54 return {LLDB_INVALID_REGNUM, arm64_dwarf::cpsr};
55 return MCBasedABI::GetEHAndDWARFNums(name);
56 }
57
GetMCName(std::string reg)58 std::string ABIAArch64::GetMCName(std::string reg) {
59 MapRegisterName(reg, "v", "q");
60 MapRegisterName(reg, "x29", "fp");
61 MapRegisterName(reg, "x30", "lr");
62 return reg;
63 }
64
GetGenericNum(llvm::StringRef name)65 uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) {
66 return llvm::StringSwitch<uint32_t>(name)
67 .Case("pc", LLDB_REGNUM_GENERIC_PC)
68 .Cases("lr", "x30", LLDB_REGNUM_GENERIC_RA)
69 .Cases("sp", "x31", LLDB_REGNUM_GENERIC_SP)
70 .Cases("fp", "x29", LLDB_REGNUM_GENERIC_FP)
71 .Case("cpsr", LLDB_REGNUM_GENERIC_FLAGS)
72 .Case("x0", LLDB_REGNUM_GENERIC_ARG1)
73 .Case("x1", LLDB_REGNUM_GENERIC_ARG2)
74 .Case("x2", LLDB_REGNUM_GENERIC_ARG3)
75 .Case("x3", LLDB_REGNUM_GENERIC_ARG4)
76 .Case("x4", LLDB_REGNUM_GENERIC_ARG5)
77 .Case("x5", LLDB_REGNUM_GENERIC_ARG6)
78 .Case("x6", LLDB_REGNUM_GENERIC_ARG7)
79 .Case("x7", LLDB_REGNUM_GENERIC_ARG8)
80 .Default(LLDB_INVALID_REGNUM);
81 }
82
addPartialRegisters(std::vector<lldb_private::DynamicRegisterInfo::Register> & regs,llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,uint32_t full_reg_size,const char * partial_reg_format,uint32_t partial_reg_size,lldb::Encoding encoding,lldb::Format format)83 static void addPartialRegisters(
84 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s,
85 llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices,
86 uint32_t full_reg_size, const char *partial_reg_format,
87 uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {
88 for (auto it : llvm::enumerate(full_reg_indices)) {
89 std::optional<uint32_t> full_reg_index = it.value();
90 if (!full_reg_index || regs[*full_reg_index].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},
107 {}};
108 addSupplementaryRegister(regs, partial_reg);
109 }
110 }
111
AugmentRegisterInfo(std::vector<lldb_private::DynamicRegisterInfo::Register> & regs)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<std::optional<uint32_t>, 32> x_regs;
119 std::array<std::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