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