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