1 | //===-- DynamicRegisterInfo.cpp -------------------------------------------===// |
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/Target/DynamicRegisterInfo.h" |
10 | #include "lldb/DataFormatters/FormatManager.h" |
11 | #include "lldb/Host/StreamFile.h" |
12 | #include "lldb/Interpreter/OptionArgParser.h" |
13 | #include "lldb/Utility/ArchSpec.h" |
14 | #include "lldb/Utility/LLDBLog.h" |
15 | #include "lldb/Utility/Log.h" |
16 | #include "lldb/Utility/RegularExpression.h" |
17 | #include "lldb/Utility/StringExtractor.h" |
18 | #include "lldb/Utility/StructuredData.h" |
19 | |
20 | using namespace lldb; |
21 | using namespace lldb_private; |
22 | |
23 | std::unique_ptr<DynamicRegisterInfo> |
24 | DynamicRegisterInfo::Create(const StructuredData::Dictionary &dict, |
25 | const ArchSpec &arch) { |
26 | auto dyn_reg_info = std::make_unique<DynamicRegisterInfo>(); |
27 | if (!dyn_reg_info) |
28 | return nullptr; |
29 | |
30 | if (dyn_reg_info->SetRegisterInfo(dict, arch) == 0) |
31 | return nullptr; |
32 | |
33 | return dyn_reg_info; |
34 | } |
35 | |
36 | DynamicRegisterInfo::DynamicRegisterInfo(DynamicRegisterInfo &&info) { |
37 | MoveFrom(info: std::move(info)); |
38 | } |
39 | |
40 | DynamicRegisterInfo & |
41 | DynamicRegisterInfo::operator=(DynamicRegisterInfo &&info) { |
42 | MoveFrom(info: std::move(info)); |
43 | return *this; |
44 | } |
45 | |
46 | void DynamicRegisterInfo::MoveFrom(DynamicRegisterInfo &&info) { |
47 | m_regs = std::move(info.m_regs); |
48 | m_sets = std::move(info.m_sets); |
49 | m_set_reg_nums = std::move(info.m_set_reg_nums); |
50 | m_set_names = std::move(info.m_set_names); |
51 | m_value_regs_map = std::move(info.m_value_regs_map); |
52 | m_invalidate_regs_map = std::move(info.m_invalidate_regs_map); |
53 | |
54 | m_reg_data_byte_size = info.m_reg_data_byte_size; |
55 | m_finalized = info.m_finalized; |
56 | |
57 | if (m_finalized) { |
58 | const size_t num_sets = m_sets.size(); |
59 | for (size_t set = 0; set < num_sets; ++set) |
60 | m_sets[set].registers = m_set_reg_nums[set].data(); |
61 | } |
62 | |
63 | info.Clear(); |
64 | } |
65 | |
66 | llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromSlice( |
67 | uint32_t index, llvm::StringRef slice_str, lldb::ByteOrder byte_order) { |
68 | // Slices use the following format: |
69 | // REGNAME[MSBIT:LSBIT] |
70 | // REGNAME - name of the register to grab a slice of |
71 | // MSBIT - the most significant bit at which the current register value |
72 | // starts at |
73 | // LSBIT - the least significant bit at which the current register value |
74 | // ends at |
75 | static llvm::Regex g_bitfield_regex( |
76 | "([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]" ); |
77 | llvm::SmallVector<llvm::StringRef, 4> matches; |
78 | if (!g_bitfield_regex.match(String: slice_str, Matches: &matches)) |
79 | return llvm::createStringError( |
80 | EC: llvm::inconvertibleErrorCode(), |
81 | Fmt: "failed to match against register bitfield regex (slice: %s)" , |
82 | Vals: slice_str.str().c_str()); |
83 | |
84 | llvm::StringRef reg_name_str = matches[1]; |
85 | llvm::StringRef msbit_str = matches[2]; |
86 | llvm::StringRef lsbit_str = matches[3]; |
87 | uint32_t msbit; |
88 | uint32_t lsbit; |
89 | if (!llvm::to_integer(S: msbit_str, Num&: msbit) || |
90 | !llvm::to_integer(S: lsbit_str, Num&: lsbit)) |
91 | return llvm::createStringError( |
92 | EC: llvm::inconvertibleErrorCode(), Fmt: "msbit (%s) or lsbit (%s) are invalid" , |
93 | Vals: msbit_str.str().c_str(), Vals: lsbit_str.str().c_str()); |
94 | |
95 | if (msbit <= lsbit) |
96 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
97 | Fmt: "msbit (%u) must be greater than lsbit (%u)" , |
98 | Vals: msbit, Vals: lsbit); |
99 | |
100 | const uint32_t msbyte = msbit / 8; |
101 | const uint32_t lsbyte = lsbit / 8; |
102 | |
103 | const RegisterInfo *containing_reg_info = GetRegisterInfo(reg_name: reg_name_str); |
104 | if (!containing_reg_info) |
105 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
106 | Fmt: "invalid concrete register \"%s\"" , |
107 | Vals: reg_name_str.str().c_str()); |
108 | |
109 | const uint32_t max_bit = containing_reg_info->byte_size * 8; |
110 | |
111 | if (msbit > max_bit) |
112 | return llvm::createStringError( |
113 | EC: llvm::inconvertibleErrorCode(), |
114 | Fmt: "msbit (%u) must be less than the bitsize of the register \"%s\" (%u)" , |
115 | Vals: msbit, Vals: reg_name_str.str().c_str(), Vals: max_bit); |
116 | if (lsbit > max_bit) |
117 | return llvm::createStringError( |
118 | EC: llvm::inconvertibleErrorCode(), |
119 | Fmt: "lsbit (%u) must be less than the bitsize of the register \"%s\" (%u)" , |
120 | Vals: lsbit, Vals: reg_name_str.str().c_str(), Vals: max_bit); |
121 | |
122 | m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]] |
123 | .push_back(x: index); |
124 | m_value_regs_map[index].push_back( |
125 | x: containing_reg_info->kinds[eRegisterKindLLDB]); |
126 | m_invalidate_regs_map[index].push_back( |
127 | x: containing_reg_info->kinds[eRegisterKindLLDB]); |
128 | |
129 | if (byte_order == eByteOrderLittle) |
130 | return containing_reg_info->byte_offset + lsbyte; |
131 | if (byte_order == eByteOrderBig) |
132 | return containing_reg_info->byte_offset + msbyte; |
133 | llvm_unreachable("Invalid byte order" ); |
134 | } |
135 | |
136 | llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromComposite( |
137 | uint32_t index, StructuredData::Array &composite_reg_list, |
138 | lldb::ByteOrder byte_order) { |
139 | const size_t num_composite_regs = composite_reg_list.GetSize(); |
140 | if (num_composite_regs == 0) |
141 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
142 | Msg: "\"composite\" list is empty" ); |
143 | |
144 | uint32_t composite_offset = UINT32_MAX; |
145 | for (uint32_t composite_idx = 0; composite_idx < num_composite_regs; |
146 | ++composite_idx) { |
147 | std::optional<llvm::StringRef> maybe_composite_reg_name = |
148 | composite_reg_list.GetItemAtIndexAsString(idx: composite_idx); |
149 | if (!maybe_composite_reg_name) |
150 | return llvm::createStringError( |
151 | EC: llvm::inconvertibleErrorCode(), |
152 | Fmt: "\"composite\" list value is not a Python string at index %d" , |
153 | Vals: composite_idx); |
154 | |
155 | const RegisterInfo *composite_reg_info = |
156 | GetRegisterInfo(reg_name: *maybe_composite_reg_name); |
157 | if (!composite_reg_info) |
158 | return llvm::createStringError( |
159 | EC: llvm::inconvertibleErrorCode(), |
160 | Fmt: "failed to find composite register by name: \"%s\"" , |
161 | Vals: maybe_composite_reg_name->str().c_str()); |
162 | |
163 | composite_offset = |
164 | std::min(a: composite_offset, b: composite_reg_info->byte_offset); |
165 | m_value_regs_map[index].push_back( |
166 | x: composite_reg_info->kinds[eRegisterKindLLDB]); |
167 | m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]] |
168 | .push_back(x: index); |
169 | m_invalidate_regs_map[index].push_back( |
170 | x: composite_reg_info->kinds[eRegisterKindLLDB]); |
171 | } |
172 | |
173 | return composite_offset; |
174 | } |
175 | |
176 | llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromRegInfoDict( |
177 | uint32_t index, StructuredData::Dictionary ®_info_dict, |
178 | lldb::ByteOrder byte_order) { |
179 | uint32_t byte_offset; |
180 | if (reg_info_dict.GetValueForKeyAsInteger(key: "offset" , result&: byte_offset)) |
181 | return byte_offset; |
182 | |
183 | // No offset for this register, see if the register has a value |
184 | // expression which indicates this register is part of another register. |
185 | // Value expressions are things like "rax[31:0]" which state that the |
186 | // current register's value is in a concrete register "rax" in bits 31:0. |
187 | // If there is a value expression we can calculate the offset |
188 | llvm::StringRef slice_str; |
189 | if (reg_info_dict.GetValueForKeyAsString(key: "slice" , result&: slice_str, default_val: nullptr)) |
190 | return ByteOffsetFromSlice(index, slice_str, byte_order); |
191 | |
192 | StructuredData::Array *composite_reg_list; |
193 | if (reg_info_dict.GetValueForKeyAsArray(key: "composite" , result&: composite_reg_list)) |
194 | return ByteOffsetFromComposite(index, composite_reg_list&: *composite_reg_list, byte_order); |
195 | |
196 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
197 | Msg: "insufficient data to calculate byte offset" ); |
198 | } |
199 | |
200 | size_t |
201 | DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, |
202 | const ArchSpec &arch) { |
203 | Log *log = GetLog(mask: LLDBLog::Object); |
204 | assert(!m_finalized); |
205 | StructuredData::Array *sets = nullptr; |
206 | if (dict.GetValueForKeyAsArray(key: "sets" , result&: sets)) { |
207 | const uint32_t num_sets = sets->GetSize(); |
208 | for (uint32_t i = 0; i < num_sets; ++i) { |
209 | std::optional<llvm::StringRef> maybe_set_name = |
210 | sets->GetItemAtIndexAsString(idx: i); |
211 | if (maybe_set_name && !maybe_set_name->empty()) { |
212 | m_sets.push_back( |
213 | x: {.name: ConstString(*maybe_set_name).AsCString(), .short_name: nullptr, .num_registers: 0, .registers: nullptr}); |
214 | } else { |
215 | Clear(); |
216 | printf(format: "error: register sets must have valid names\n" ); |
217 | return 0; |
218 | } |
219 | } |
220 | m_set_reg_nums.resize(new_size: m_sets.size()); |
221 | } |
222 | |
223 | StructuredData::Array *regs = nullptr; |
224 | if (!dict.GetValueForKeyAsArray(key: "registers" , result&: regs)) |
225 | return 0; |
226 | |
227 | const ByteOrder byte_order = arch.GetByteOrder(); |
228 | |
229 | const uint32_t num_regs = regs->GetSize(); |
230 | // typedef std::map<std::string, std::vector<std::string> > |
231 | // InvalidateNameMap; |
232 | // InvalidateNameMap invalidate_map; |
233 | for (uint32_t i = 0; i < num_regs; ++i) { |
234 | std::optional<StructuredData::Dictionary *> maybe_reg_info_dict = |
235 | regs->GetItemAtIndexAsDictionary(idx: i); |
236 | if (!maybe_reg_info_dict) { |
237 | Clear(); |
238 | printf(format: "error: items in the 'registers' array must be dictionaries\n" ); |
239 | regs->DumpToStdout(); |
240 | return 0; |
241 | } |
242 | StructuredData::Dictionary *reg_info_dict = *maybe_reg_info_dict; |
243 | |
244 | // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, |
245 | // 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2, |
246 | // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }, |
247 | RegisterInfo reg_info; |
248 | std::vector<uint32_t> value_regs; |
249 | std::vector<uint32_t> invalidate_regs; |
250 | memset(s: ®_info, c: 0, n: sizeof(reg_info)); |
251 | |
252 | llvm::StringRef name_val; |
253 | if (!reg_info_dict->GetValueForKeyAsString(key: "name" , result&: name_val)) { |
254 | Clear(); |
255 | printf(format: "error: registers must have valid names and offsets\n" ); |
256 | reg_info_dict->DumpToStdout(); |
257 | return 0; |
258 | } |
259 | reg_info.name = ConstString(name_val).GetCString(); |
260 | |
261 | llvm::StringRef alt_name_val; |
262 | if (reg_info_dict->GetValueForKeyAsString(key: "alt-name" , result&: alt_name_val)) |
263 | reg_info.alt_name = ConstString(alt_name_val).GetCString(); |
264 | else |
265 | reg_info.alt_name = nullptr; |
266 | |
267 | llvm::Expected<uint32_t> byte_offset = |
268 | ByteOffsetFromRegInfoDict(index: i, reg_info_dict&: *reg_info_dict, byte_order); |
269 | if (byte_offset) |
270 | reg_info.byte_offset = byte_offset.get(); |
271 | else { |
272 | LLDB_LOG_ERROR(log, byte_offset.takeError(), |
273 | "error while parsing register {1}: {0}" , reg_info.name); |
274 | Clear(); |
275 | reg_info_dict->DumpToStdout(); |
276 | return 0; |
277 | } |
278 | |
279 | uint64_t bitsize = 0; |
280 | if (!reg_info_dict->GetValueForKeyAsInteger(key: "bitsize" , result&: bitsize)) { |
281 | Clear(); |
282 | printf(format: "error: invalid or missing 'bitsize' key/value pair in register " |
283 | "dictionary\n" ); |
284 | reg_info_dict->DumpToStdout(); |
285 | return 0; |
286 | } |
287 | |
288 | reg_info.byte_size = bitsize / 8; |
289 | |
290 | llvm::StringRef format_str; |
291 | if (reg_info_dict->GetValueForKeyAsString(key: "format" , result&: format_str, default_val: nullptr)) { |
292 | if (OptionArgParser::ToFormat(s: format_str.str().c_str(), format&: reg_info.format, |
293 | byte_size_ptr: nullptr) |
294 | .Fail()) { |
295 | Clear(); |
296 | printf(format: "error: invalid 'format' value in register dictionary\n" ); |
297 | reg_info_dict->DumpToStdout(); |
298 | return 0; |
299 | } |
300 | } else { |
301 | reg_info_dict->GetValueForKeyAsInteger(key: "format" , result&: reg_info.format, |
302 | default_val: eFormatHex); |
303 | } |
304 | |
305 | llvm::StringRef encoding_str; |
306 | if (reg_info_dict->GetValueForKeyAsString(key: "encoding" , result&: encoding_str)) |
307 | reg_info.encoding = Args::StringToEncoding(s: encoding_str, fail_value: eEncodingUint); |
308 | else |
309 | reg_info_dict->GetValueForKeyAsInteger(key: "encoding" , result&: reg_info.encoding, |
310 | default_val: eEncodingUint); |
311 | |
312 | size_t set = 0; |
313 | if (!reg_info_dict->GetValueForKeyAsInteger(key: "set" , result&: set) || |
314 | set >= m_sets.size()) { |
315 | Clear(); |
316 | printf(format: "error: invalid 'set' value in register dictionary, valid values " |
317 | "are 0 - %i\n" , |
318 | (int)set); |
319 | reg_info_dict->DumpToStdout(); |
320 | return 0; |
321 | } |
322 | |
323 | // Fill in the register numbers |
324 | reg_info.kinds[lldb::eRegisterKindLLDB] = i; |
325 | reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i; |
326 | uint32_t eh_frame_regno = LLDB_INVALID_REGNUM; |
327 | reg_info_dict->GetValueForKeyAsInteger(key: "gcc" , result&: eh_frame_regno, |
328 | LLDB_INVALID_REGNUM); |
329 | if (eh_frame_regno == LLDB_INVALID_REGNUM) |
330 | reg_info_dict->GetValueForKeyAsInteger(key: "ehframe" , result&: eh_frame_regno, |
331 | LLDB_INVALID_REGNUM); |
332 | reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno; |
333 | reg_info_dict->GetValueForKeyAsInteger( |
334 | key: "dwarf" , result&: reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM); |
335 | llvm::StringRef generic_str; |
336 | if (reg_info_dict->GetValueForKeyAsString(key: "generic" , result&: generic_str)) |
337 | reg_info.kinds[lldb::eRegisterKindGeneric] = |
338 | Args::StringToGenericRegister(s: generic_str); |
339 | else |
340 | reg_info_dict->GetValueForKeyAsInteger( |
341 | key: "generic" , result&: reg_info.kinds[lldb::eRegisterKindGeneric], |
342 | LLDB_INVALID_REGNUM); |
343 | |
344 | // Check if this register invalidates any other register values when it is |
345 | // modified |
346 | StructuredData::Array *invalidate_reg_list = nullptr; |
347 | if (reg_info_dict->GetValueForKeyAsArray(key: "invalidate-regs" , |
348 | result&: invalidate_reg_list)) { |
349 | const size_t num_regs = invalidate_reg_list->GetSize(); |
350 | if (num_regs > 0) { |
351 | for (uint32_t idx = 0; idx < num_regs; ++idx) { |
352 | if (auto maybe_invalidate_reg_name = |
353 | invalidate_reg_list->GetItemAtIndexAsString(idx)) { |
354 | const RegisterInfo *invalidate_reg_info = |
355 | GetRegisterInfo(reg_name: *maybe_invalidate_reg_name); |
356 | if (invalidate_reg_info) { |
357 | m_invalidate_regs_map[i].push_back( |
358 | x: invalidate_reg_info->kinds[eRegisterKindLLDB]); |
359 | } else { |
360 | // TODO: print error invalid slice string that doesn't follow the |
361 | // format |
362 | printf(format: "error: failed to find a 'invalidate-regs' register for " |
363 | "\"%s\" while parsing register \"%s\"\n" , |
364 | maybe_invalidate_reg_name->str().c_str(), reg_info.name); |
365 | } |
366 | } else if (auto maybe_invalidate_reg_num = |
367 | invalidate_reg_list->GetItemAtIndexAsInteger<uint64_t>( |
368 | idx)) { |
369 | if (*maybe_invalidate_reg_num != UINT64_MAX) |
370 | m_invalidate_regs_map[i].push_back(x: *maybe_invalidate_reg_num); |
371 | else |
372 | printf(format: "error: 'invalidate-regs' list value wasn't a valid " |
373 | "integer\n" ); |
374 | } else { |
375 | printf(format: "error: 'invalidate-regs' list value wasn't a python string " |
376 | "or integer\n" ); |
377 | } |
378 | } |
379 | } else { |
380 | printf(format: "error: 'invalidate-regs' contained an empty list\n" ); |
381 | } |
382 | } |
383 | |
384 | // Calculate the register offset |
385 | const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; |
386 | if (m_reg_data_byte_size < end_reg_offset) |
387 | m_reg_data_byte_size = end_reg_offset; |
388 | |
389 | m_regs.push_back(x: reg_info); |
390 | m_set_reg_nums[set].push_back(x: i); |
391 | } |
392 | Finalize(arch); |
393 | return m_regs.size(); |
394 | } |
395 | |
396 | size_t DynamicRegisterInfo::SetRegisterInfo( |
397 | std::vector<DynamicRegisterInfo::Register> &®s, |
398 | const ArchSpec &arch) { |
399 | assert(!m_finalized); |
400 | |
401 | for (auto it : llvm::enumerate(First&: regs)) { |
402 | uint32_t local_regnum = it.index(); |
403 | const DynamicRegisterInfo::Register ® = it.value(); |
404 | |
405 | assert(reg.name); |
406 | assert(reg.set_name); |
407 | |
408 | if (!reg.value_regs.empty()) |
409 | m_value_regs_map[local_regnum] = std::move(reg.value_regs); |
410 | if (!reg.invalidate_regs.empty()) |
411 | m_invalidate_regs_map[local_regnum] = std::move(reg.invalidate_regs); |
412 | if (reg.value_reg_offset != 0) { |
413 | assert(reg.value_regs.size() == 1); |
414 | m_value_reg_offset_map[local_regnum] = reg.value_reg_offset; |
415 | } |
416 | |
417 | struct RegisterInfo reg_info { |
418 | .name: reg.name.AsCString(), .alt_name: reg.alt_name.AsCString(), .byte_size: reg.byte_size, |
419 | .byte_offset: reg.byte_offset, .encoding: reg.encoding, .format: reg.format, |
420 | .kinds: {reg.regnum_ehframe, reg.regnum_dwarf, reg.regnum_generic, |
421 | reg.regnum_remote, local_regnum}, |
422 | // value_regs and invalidate_regs are filled by Finalize() |
423 | .value_regs: nullptr, .invalidate_regs: nullptr, .flags_type: reg.flags_type |
424 | }; |
425 | |
426 | m_regs.push_back(x: reg_info); |
427 | |
428 | uint32_t set = GetRegisterSetIndexByName(set_name: reg.set_name, can_create: true); |
429 | assert(set < m_sets.size()); |
430 | assert(set < m_set_reg_nums.size()); |
431 | assert(set < m_set_names.size()); |
432 | m_set_reg_nums[set].push_back(x: local_regnum); |
433 | }; |
434 | |
435 | Finalize(arch); |
436 | return m_regs.size(); |
437 | } |
438 | |
439 | void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { |
440 | if (m_finalized) |
441 | return; |
442 | |
443 | m_finalized = true; |
444 | const size_t num_sets = m_sets.size(); |
445 | for (size_t set = 0; set < num_sets; ++set) { |
446 | assert(m_sets.size() == m_set_reg_nums.size()); |
447 | m_sets[set].num_registers = m_set_reg_nums[set].size(); |
448 | m_sets[set].registers = m_set_reg_nums[set].data(); |
449 | } |
450 | |
451 | // make sure value_regs are terminated with LLDB_INVALID_REGNUM |
452 | |
453 | for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), |
454 | end = m_value_regs_map.end(); |
455 | pos != end; ++pos) { |
456 | if (pos->second.back() != LLDB_INVALID_REGNUM) |
457 | pos->second.push_back(LLDB_INVALID_REGNUM); |
458 | } |
459 | |
460 | // Now update all value_regs with each register info as needed |
461 | const size_t num_regs = m_regs.size(); |
462 | for (size_t i = 0; i < num_regs; ++i) { |
463 | if (m_value_regs_map.find(x: i) != m_value_regs_map.end()) |
464 | m_regs[i].value_regs = m_value_regs_map[i].data(); |
465 | else |
466 | m_regs[i].value_regs = nullptr; |
467 | } |
468 | |
469 | // Expand all invalidation dependencies |
470 | for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), |
471 | end = m_invalidate_regs_map.end(); |
472 | pos != end; ++pos) { |
473 | const uint32_t reg_num = pos->first; |
474 | |
475 | if (m_regs[reg_num].value_regs) { |
476 | reg_num_collection ; |
477 | for (const uint32_t invalidate_reg_num : pos->second) { |
478 | reg_to_regs_map::iterator invalidate_pos = |
479 | m_invalidate_regs_map.find(x: invalidate_reg_num); |
480 | if (invalidate_pos != m_invalidate_regs_map.end()) { |
481 | for (const uint32_t concrete_invalidate_reg_num : |
482 | invalidate_pos->second) { |
483 | if (concrete_invalidate_reg_num != reg_num) |
484 | extra_invalid_regs.push_back(x: concrete_invalidate_reg_num); |
485 | } |
486 | } |
487 | } |
488 | pos->second.insert(position: pos->second.end(), first: extra_invalid_regs.begin(), |
489 | last: extra_invalid_regs.end()); |
490 | } |
491 | } |
492 | |
493 | // sort and unique all invalidate registers and make sure each is terminated |
494 | // with LLDB_INVALID_REGNUM |
495 | for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), |
496 | end = m_invalidate_regs_map.end(); |
497 | pos != end; ++pos) { |
498 | if (pos->second.size() > 1) { |
499 | llvm::sort(C&: pos->second); |
500 | reg_num_collection::iterator unique_end = |
501 | std::unique(first: pos->second.begin(), last: pos->second.end()); |
502 | if (unique_end != pos->second.end()) |
503 | pos->second.erase(first: unique_end, last: pos->second.end()); |
504 | } |
505 | assert(!pos->second.empty()); |
506 | if (pos->second.back() != LLDB_INVALID_REGNUM) |
507 | pos->second.push_back(LLDB_INVALID_REGNUM); |
508 | } |
509 | |
510 | // Now update all invalidate_regs with each register info as needed |
511 | for (size_t i = 0; i < num_regs; ++i) { |
512 | if (m_invalidate_regs_map.find(x: i) != m_invalidate_regs_map.end()) |
513 | m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data(); |
514 | else |
515 | m_regs[i].invalidate_regs = nullptr; |
516 | } |
517 | |
518 | // Check if we need to automatically set the generic registers in case they |
519 | // weren't set |
520 | bool generic_regs_specified = false; |
521 | for (const auto ® : m_regs) { |
522 | if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) { |
523 | generic_regs_specified = true; |
524 | break; |
525 | } |
526 | } |
527 | |
528 | if (!generic_regs_specified) { |
529 | switch (arch.GetMachine()) { |
530 | case llvm::Triple::aarch64: |
531 | case llvm::Triple::aarch64_32: |
532 | case llvm::Triple::aarch64_be: |
533 | for (auto ® : m_regs) { |
534 | if (strcmp(s1: reg.name, s2: "pc" ) == 0) |
535 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
536 | else if ((strcmp(s1: reg.name, s2: "fp" ) == 0) || |
537 | (strcmp(s1: reg.name, s2: "x29" ) == 0)) |
538 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
539 | else if ((strcmp(s1: reg.name, s2: "lr" ) == 0) || |
540 | (strcmp(s1: reg.name, s2: "x30" ) == 0)) |
541 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; |
542 | else if ((strcmp(s1: reg.name, s2: "sp" ) == 0) || |
543 | (strcmp(s1: reg.name, s2: "x31" ) == 0)) |
544 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
545 | else if (strcmp(s1: reg.name, s2: "cpsr" ) == 0) |
546 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
547 | } |
548 | break; |
549 | |
550 | case llvm::Triple::arm: |
551 | case llvm::Triple::armeb: |
552 | case llvm::Triple::thumb: |
553 | case llvm::Triple::thumbeb: |
554 | for (auto ® : m_regs) { |
555 | if ((strcmp(s1: reg.name, s2: "pc" ) == 0) || (strcmp(s1: reg.name, s2: "r15" ) == 0)) |
556 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
557 | else if ((strcmp(s1: reg.name, s2: "sp" ) == 0) || |
558 | (strcmp(s1: reg.name, s2: "r13" ) == 0)) |
559 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
560 | else if ((strcmp(s1: reg.name, s2: "lr" ) == 0) || |
561 | (strcmp(s1: reg.name, s2: "r14" ) == 0)) |
562 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; |
563 | else if ((strcmp(s1: reg.name, s2: "r7" ) == 0) && |
564 | arch.GetTriple().getVendor() == llvm::Triple::Apple) |
565 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
566 | else if ((strcmp(s1: reg.name, s2: "r11" ) == 0) && |
567 | arch.GetTriple().getVendor() != llvm::Triple::Apple) |
568 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
569 | else if (strcmp(s1: reg.name, s2: "fp" ) == 0) |
570 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
571 | else if (strcmp(s1: reg.name, s2: "cpsr" ) == 0) |
572 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
573 | } |
574 | break; |
575 | |
576 | case llvm::Triple::x86: |
577 | for (auto ® : m_regs) { |
578 | if ((strcmp(s1: reg.name, s2: "eip" ) == 0) || (strcmp(s1: reg.name, s2: "pc" ) == 0)) |
579 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
580 | else if ((strcmp(s1: reg.name, s2: "esp" ) == 0) || |
581 | (strcmp(s1: reg.name, s2: "sp" ) == 0)) |
582 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
583 | else if ((strcmp(s1: reg.name, s2: "ebp" ) == 0) || |
584 | (strcmp(s1: reg.name, s2: "fp" ) == 0)) |
585 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
586 | else if ((strcmp(s1: reg.name, s2: "eflags" ) == 0) || |
587 | (strcmp(s1: reg.name, s2: "flags" ) == 0)) |
588 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
589 | } |
590 | break; |
591 | |
592 | case llvm::Triple::x86_64: |
593 | for (auto ® : m_regs) { |
594 | if ((strcmp(s1: reg.name, s2: "rip" ) == 0) || (strcmp(s1: reg.name, s2: "pc" ) == 0)) |
595 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
596 | else if ((strcmp(s1: reg.name, s2: "rsp" ) == 0) || |
597 | (strcmp(s1: reg.name, s2: "sp" ) == 0)) |
598 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
599 | else if ((strcmp(s1: reg.name, s2: "rbp" ) == 0) || |
600 | (strcmp(s1: reg.name, s2: "fp" ) == 0)) |
601 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
602 | else if ((strcmp(s1: reg.name, s2: "rflags" ) == 0) || |
603 | (strcmp(s1: reg.name, s2: "eflags" ) == 0) || |
604 | (strcmp(s1: reg.name, s2: "flags" ) == 0)) |
605 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
606 | } |
607 | break; |
608 | |
609 | default: |
610 | break; |
611 | } |
612 | } |
613 | |
614 | // At this stage call ConfigureOffsets to calculate register offsets for |
615 | // targets supporting dynamic offset calculation. It also calculates |
616 | // total byte size of register data. |
617 | ConfigureOffsets(); |
618 | |
619 | // Check if register info is reconfigurable |
620 | // AArch64 SVE register set has configurable register sizes, as does the ZA |
621 | // register that SME added (the streaming state of SME reuses the SVE state). |
622 | if (arch.GetTriple().isAArch64()) { |
623 | for (const auto ® : m_regs) { |
624 | if ((strcmp(s1: reg.name, s2: "vg" ) == 0) || (strcmp(s1: reg.name, s2: "svg" ) == 0)) { |
625 | m_is_reconfigurable = true; |
626 | break; |
627 | } |
628 | } |
629 | } |
630 | } |
631 | |
632 | void DynamicRegisterInfo::ConfigureOffsets() { |
633 | // We are going to create a map between remote (eRegisterKindProcessPlugin) |
634 | // and local (eRegisterKindLLDB) register numbers. This map will give us |
635 | // remote register numbers in increasing order for offset calculation. |
636 | std::map<uint32_t, uint32_t> remote_to_local_regnum_map; |
637 | for (const auto ® : m_regs) |
638 | remote_to_local_regnum_map[reg.kinds[eRegisterKindProcessPlugin]] = |
639 | reg.kinds[eRegisterKindLLDB]; |
640 | |
641 | // At this stage we manually calculate g/G packet offsets of all primary |
642 | // registers, only if target XML or qRegisterInfo packet did not send |
643 | // an offset explicitly. |
644 | uint32_t reg_offset = 0; |
645 | for (auto const ®num_pair : remote_to_local_regnum_map) { |
646 | if (m_regs[regnum_pair.second].byte_offset == LLDB_INVALID_INDEX32 && |
647 | m_regs[regnum_pair.second].value_regs == nullptr) { |
648 | m_regs[regnum_pair.second].byte_offset = reg_offset; |
649 | |
650 | reg_offset = m_regs[regnum_pair.second].byte_offset + |
651 | m_regs[regnum_pair.second].byte_size; |
652 | } |
653 | } |
654 | |
655 | // Now update all value_regs with each register info as needed |
656 | for (auto ® : m_regs) { |
657 | if (reg.value_regs != nullptr) { |
658 | // Assign a valid offset to all pseudo registers that have only a single |
659 | // parent register in value_regs list, if not assigned by stub. Pseudo |
660 | // registers with value_regs list populated will share same offset as |
661 | // that of their corresponding parent register. |
662 | if (reg.byte_offset == LLDB_INVALID_INDEX32) { |
663 | uint32_t value_regnum = reg.value_regs[0]; |
664 | if (value_regnum != LLDB_INVALID_INDEX32 && |
665 | reg.value_regs[1] == LLDB_INVALID_INDEX32) { |
666 | reg.byte_offset = |
667 | GetRegisterInfoAtIndex(i: value_regnum)->byte_offset; |
668 | auto it = m_value_reg_offset_map.find(x: reg.kinds[eRegisterKindLLDB]); |
669 | if (it != m_value_reg_offset_map.end()) |
670 | reg.byte_offset += it->second; |
671 | } |
672 | } |
673 | } |
674 | |
675 | reg_offset = reg.byte_offset + reg.byte_size; |
676 | if (m_reg_data_byte_size < reg_offset) |
677 | m_reg_data_byte_size = reg_offset; |
678 | } |
679 | } |
680 | |
681 | bool DynamicRegisterInfo::IsReconfigurable() { return m_is_reconfigurable; } |
682 | |
683 | size_t DynamicRegisterInfo::GetNumRegisters() const { return m_regs.size(); } |
684 | |
685 | size_t DynamicRegisterInfo::GetNumRegisterSets() const { return m_sets.size(); } |
686 | |
687 | size_t DynamicRegisterInfo::GetRegisterDataByteSize() const { |
688 | return m_reg_data_byte_size; |
689 | } |
690 | |
691 | const RegisterInfo * |
692 | DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) const { |
693 | if (i < m_regs.size()) |
694 | return &m_regs[i]; |
695 | return nullptr; |
696 | } |
697 | |
698 | const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind, |
699 | uint32_t num) const { |
700 | uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num); |
701 | if (reg_index != LLDB_INVALID_REGNUM) |
702 | return &m_regs[reg_index]; |
703 | return nullptr; |
704 | } |
705 | |
706 | const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const { |
707 | if (i < m_sets.size()) |
708 | return &m_sets[i]; |
709 | return nullptr; |
710 | } |
711 | |
712 | uint32_t |
713 | DynamicRegisterInfo::GetRegisterSetIndexByName(const ConstString &set_name, |
714 | bool can_create) { |
715 | name_collection::iterator pos, end = m_set_names.end(); |
716 | for (pos = m_set_names.begin(); pos != end; ++pos) { |
717 | if (*pos == set_name) |
718 | return std::distance(first: m_set_names.begin(), last: pos); |
719 | } |
720 | |
721 | m_set_names.push_back(x: set_name); |
722 | m_set_reg_nums.resize(new_size: m_set_reg_nums.size() + 1); |
723 | RegisterSet new_set = {.name: set_name.AsCString(), .short_name: nullptr, .num_registers: 0, .registers: nullptr}; |
724 | m_sets.push_back(x: new_set); |
725 | return m_sets.size() - 1; |
726 | } |
727 | |
728 | uint32_t |
729 | DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber(uint32_t kind, |
730 | uint32_t num) const { |
731 | reg_collection::const_iterator pos, end = m_regs.end(); |
732 | for (pos = m_regs.begin(); pos != end; ++pos) { |
733 | if (pos->kinds[kind] == num) |
734 | return std::distance(first: m_regs.begin(), last: pos); |
735 | } |
736 | |
737 | return LLDB_INVALID_REGNUM; |
738 | } |
739 | |
740 | void DynamicRegisterInfo::Clear() { |
741 | m_regs.clear(); |
742 | m_sets.clear(); |
743 | m_set_reg_nums.clear(); |
744 | m_set_names.clear(); |
745 | m_value_regs_map.clear(); |
746 | m_invalidate_regs_map.clear(); |
747 | m_reg_data_byte_size = 0; |
748 | m_finalized = false; |
749 | } |
750 | |
751 | void DynamicRegisterInfo::Dump() const { |
752 | StreamFile s(stdout, false); |
753 | const size_t num_regs = m_regs.size(); |
754 | s.Printf(format: "%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n" , |
755 | static_cast<const void *>(this), static_cast<uint64_t>(num_regs)); |
756 | for (size_t i = 0; i < num_regs; ++i) { |
757 | s.Printf(format: "[%3" PRIu64 "] name = %-10s" , (uint64_t)i, m_regs[i].name); |
758 | s.Printf(format: ", size = %2u, offset = %4u, encoding = %u, format = %-10s" , |
759 | m_regs[i].byte_size, m_regs[i].byte_offset, m_regs[i].encoding, |
760 | FormatManager::GetFormatAsCString(format: m_regs[i].format)); |
761 | if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM) |
762 | s.Printf(format: ", process plugin = %3u" , |
763 | m_regs[i].kinds[eRegisterKindProcessPlugin]); |
764 | if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) |
765 | s.Printf(format: ", dwarf = %3u" , m_regs[i].kinds[eRegisterKindDWARF]); |
766 | if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) |
767 | s.Printf(format: ", ehframe = %3u" , m_regs[i].kinds[eRegisterKindEHFrame]); |
768 | if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) |
769 | s.Printf(format: ", generic = %3u" , m_regs[i].kinds[eRegisterKindGeneric]); |
770 | if (m_regs[i].alt_name) |
771 | s.Printf(format: ", alt-name = %s" , m_regs[i].alt_name); |
772 | if (m_regs[i].value_regs) { |
773 | s.Printf(format: ", value_regs = [ " ); |
774 | for (size_t j = 0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) { |
775 | s.Printf(format: "%s " , m_regs[m_regs[i].value_regs[j]].name); |
776 | } |
777 | s.Printf(format: "]" ); |
778 | } |
779 | if (m_regs[i].invalidate_regs) { |
780 | s.Printf(format: ", invalidate_regs = [ " ); |
781 | for (size_t j = 0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; |
782 | ++j) { |
783 | s.Printf(format: "%s " , m_regs[m_regs[i].invalidate_regs[j]].name); |
784 | } |
785 | s.Printf(format: "]" ); |
786 | } |
787 | s.EOL(); |
788 | } |
789 | |
790 | const size_t num_sets = m_sets.size(); |
791 | s.Printf(format: "%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n" , |
792 | static_cast<const void *>(this), static_cast<uint64_t>(num_sets)); |
793 | for (size_t i = 0; i < num_sets; ++i) { |
794 | s.Printf(format: "set[%" PRIu64 "] name = %s, regs = [" , (uint64_t)i, |
795 | m_sets[i].name); |
796 | for (size_t idx = 0; idx < m_sets[i].num_registers; ++idx) { |
797 | s.Printf(format: "%s " , m_regs[m_sets[i].registers[idx]].name); |
798 | } |
799 | s.Printf(format: "]\n" ); |
800 | } |
801 | } |
802 | |
803 | const lldb_private::RegisterInfo * |
804 | DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) const { |
805 | for (auto ®_info : m_regs) |
806 | if (reg_info.name == reg_name) |
807 | return ®_info; |
808 | return nullptr; |
809 | } |
810 | |
811 | void lldb_private::addSupplementaryRegister( |
812 | std::vector<DynamicRegisterInfo::Register> ®s, |
813 | DynamicRegisterInfo::Register new_reg_info) { |
814 | assert(!new_reg_info.value_regs.empty()); |
815 | const uint32_t reg_num = regs.size(); |
816 | regs.push_back(x: new_reg_info); |
817 | |
818 | std::map<uint32_t, std::vector<uint32_t>> new_invalidates; |
819 | for (uint32_t value_reg : new_reg_info.value_regs) { |
820 | // copy value_regs to invalidate_regs |
821 | new_invalidates[reg_num].push_back(x: value_reg); |
822 | |
823 | // copy invalidate_regs from the parent register |
824 | llvm::append_range(C&: new_invalidates[reg_num], |
825 | R&: regs[value_reg].invalidate_regs); |
826 | |
827 | // add reverse invalidate entries |
828 | for (uint32_t x : new_invalidates[reg_num]) |
829 | new_invalidates[x].push_back(x: reg_num); |
830 | } |
831 | |
832 | for (const auto &x : new_invalidates) |
833 | llvm::append_range(C&: regs[x.first].invalidate_regs, R: x.second); |
834 | } |
835 | |