| 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 | S: "\"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 | S: "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 | memset(s: ®_info, c: 0, n: sizeof(reg_info)); |
| 249 | |
| 250 | llvm::StringRef name_val; |
| 251 | if (!reg_info_dict->GetValueForKeyAsString(key: "name" , result&: name_val)) { |
| 252 | Clear(); |
| 253 | printf(format: "error: registers must have valid names and offsets\n" ); |
| 254 | reg_info_dict->DumpToStdout(); |
| 255 | return 0; |
| 256 | } |
| 257 | reg_info.name = ConstString(name_val).GetCString(); |
| 258 | |
| 259 | llvm::StringRef alt_name_val; |
| 260 | if (reg_info_dict->GetValueForKeyAsString(key: "alt-name" , result&: alt_name_val)) |
| 261 | reg_info.alt_name = ConstString(alt_name_val).GetCString(); |
| 262 | else |
| 263 | reg_info.alt_name = nullptr; |
| 264 | |
| 265 | llvm::Expected<uint32_t> byte_offset = |
| 266 | ByteOffsetFromRegInfoDict(index: i, reg_info_dict&: *reg_info_dict, byte_order); |
| 267 | if (byte_offset) |
| 268 | reg_info.byte_offset = byte_offset.get(); |
| 269 | else { |
| 270 | LLDB_LOG_ERROR(log, byte_offset.takeError(), |
| 271 | "error while parsing register {1}: {0}" , reg_info.name); |
| 272 | Clear(); |
| 273 | reg_info_dict->DumpToStdout(); |
| 274 | return 0; |
| 275 | } |
| 276 | |
| 277 | uint64_t bitsize = 0; |
| 278 | if (!reg_info_dict->GetValueForKeyAsInteger(key: "bitsize" , result&: bitsize)) { |
| 279 | Clear(); |
| 280 | printf(format: "error: invalid or missing 'bitsize' key/value pair in register " |
| 281 | "dictionary\n" ); |
| 282 | reg_info_dict->DumpToStdout(); |
| 283 | return 0; |
| 284 | } |
| 285 | |
| 286 | reg_info.byte_size = bitsize / 8; |
| 287 | |
| 288 | llvm::StringRef format_str; |
| 289 | if (reg_info_dict->GetValueForKeyAsString(key: "format" , result&: format_str, default_val: nullptr)) { |
| 290 | if (OptionArgParser::ToFormat(s: format_str.str().c_str(), format&: reg_info.format, |
| 291 | byte_size_ptr: nullptr) |
| 292 | .Fail()) { |
| 293 | Clear(); |
| 294 | printf(format: "error: invalid 'format' value in register dictionary\n" ); |
| 295 | reg_info_dict->DumpToStdout(); |
| 296 | return 0; |
| 297 | } |
| 298 | } else { |
| 299 | reg_info_dict->GetValueForKeyAsInteger(key: "format" , result&: reg_info.format, |
| 300 | default_val: eFormatHex); |
| 301 | } |
| 302 | |
| 303 | llvm::StringRef encoding_str; |
| 304 | if (reg_info_dict->GetValueForKeyAsString(key: "encoding" , result&: encoding_str)) |
| 305 | reg_info.encoding = Args::StringToEncoding(s: encoding_str, fail_value: eEncodingUint); |
| 306 | else |
| 307 | reg_info_dict->GetValueForKeyAsInteger(key: "encoding" , result&: reg_info.encoding, |
| 308 | default_val: eEncodingUint); |
| 309 | |
| 310 | size_t set = 0; |
| 311 | if (!reg_info_dict->GetValueForKeyAsInteger(key: "set" , result&: set) || |
| 312 | set >= m_sets.size()) { |
| 313 | Clear(); |
| 314 | printf(format: "error: invalid 'set' value in register dictionary, valid values " |
| 315 | "are 0 - %i\n" , |
| 316 | (int)set); |
| 317 | reg_info_dict->DumpToStdout(); |
| 318 | return 0; |
| 319 | } |
| 320 | |
| 321 | // Fill in the register numbers |
| 322 | reg_info.kinds[lldb::eRegisterKindLLDB] = i; |
| 323 | reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i; |
| 324 | uint32_t eh_frame_regno = LLDB_INVALID_REGNUM; |
| 325 | reg_info_dict->GetValueForKeyAsInteger(key: "gcc" , result&: eh_frame_regno, |
| 326 | LLDB_INVALID_REGNUM); |
| 327 | if (eh_frame_regno == LLDB_INVALID_REGNUM) |
| 328 | reg_info_dict->GetValueForKeyAsInteger(key: "ehframe" , result&: eh_frame_regno, |
| 329 | LLDB_INVALID_REGNUM); |
| 330 | reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno; |
| 331 | reg_info_dict->GetValueForKeyAsInteger( |
| 332 | key: "dwarf" , result&: reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM); |
| 333 | llvm::StringRef generic_str; |
| 334 | if (reg_info_dict->GetValueForKeyAsString(key: "generic" , result&: generic_str)) |
| 335 | reg_info.kinds[lldb::eRegisterKindGeneric] = |
| 336 | Args::StringToGenericRegister(s: generic_str); |
| 337 | else |
| 338 | reg_info_dict->GetValueForKeyAsInteger( |
| 339 | key: "generic" , result&: reg_info.kinds[lldb::eRegisterKindGeneric], |
| 340 | LLDB_INVALID_REGNUM); |
| 341 | |
| 342 | // Check if this register invalidates any other register values when it is |
| 343 | // modified |
| 344 | StructuredData::Array *invalidate_reg_list = nullptr; |
| 345 | if (reg_info_dict->GetValueForKeyAsArray(key: "invalidate-regs" , |
| 346 | result&: invalidate_reg_list)) { |
| 347 | const size_t num_regs = invalidate_reg_list->GetSize(); |
| 348 | if (num_regs > 0) { |
| 349 | for (uint32_t idx = 0; idx < num_regs; ++idx) { |
| 350 | if (auto maybe_invalidate_reg_name = |
| 351 | invalidate_reg_list->GetItemAtIndexAsString(idx)) { |
| 352 | const RegisterInfo *invalidate_reg_info = |
| 353 | GetRegisterInfo(reg_name: *maybe_invalidate_reg_name); |
| 354 | if (invalidate_reg_info) { |
| 355 | m_invalidate_regs_map[i].push_back( |
| 356 | x: invalidate_reg_info->kinds[eRegisterKindLLDB]); |
| 357 | } else { |
| 358 | // TODO: print error invalid slice string that doesn't follow the |
| 359 | // format |
| 360 | printf(format: "error: failed to find a 'invalidate-regs' register for " |
| 361 | "\"%s\" while parsing register \"%s\"\n" , |
| 362 | maybe_invalidate_reg_name->str().c_str(), reg_info.name); |
| 363 | } |
| 364 | } else if (auto maybe_invalidate_reg_num = |
| 365 | invalidate_reg_list->GetItemAtIndexAsInteger<uint64_t>( |
| 366 | idx)) { |
| 367 | if (*maybe_invalidate_reg_num != UINT64_MAX) |
| 368 | m_invalidate_regs_map[i].push_back(x: *maybe_invalidate_reg_num); |
| 369 | else |
| 370 | printf(format: "error: 'invalidate-regs' list value wasn't a valid " |
| 371 | "integer\n" ); |
| 372 | } else { |
| 373 | printf(format: "error: 'invalidate-regs' list value wasn't a python string " |
| 374 | "or integer\n" ); |
| 375 | } |
| 376 | } |
| 377 | } else { |
| 378 | printf(format: "error: 'invalidate-regs' contained an empty list\n" ); |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | // Calculate the register offset |
| 383 | const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; |
| 384 | if (m_reg_data_byte_size < end_reg_offset) |
| 385 | m_reg_data_byte_size = end_reg_offset; |
| 386 | |
| 387 | m_regs.push_back(x: reg_info); |
| 388 | m_set_reg_nums[set].push_back(x: i); |
| 389 | } |
| 390 | Finalize(arch); |
| 391 | return m_regs.size(); |
| 392 | } |
| 393 | |
| 394 | size_t DynamicRegisterInfo::SetRegisterInfo( |
| 395 | std::vector<DynamicRegisterInfo::Register> &®s, |
| 396 | const ArchSpec &arch) { |
| 397 | assert(!m_finalized); |
| 398 | |
| 399 | for (auto it : llvm::enumerate(First&: regs)) { |
| 400 | uint32_t local_regnum = it.index(); |
| 401 | const DynamicRegisterInfo::Register ® = it.value(); |
| 402 | |
| 403 | assert(reg.name); |
| 404 | assert(reg.set_name); |
| 405 | |
| 406 | if (!reg.value_regs.empty()) |
| 407 | m_value_regs_map[local_regnum] = std::move(reg.value_regs); |
| 408 | if (!reg.invalidate_regs.empty()) |
| 409 | m_invalidate_regs_map[local_regnum] = std::move(reg.invalidate_regs); |
| 410 | if (reg.value_reg_offset != 0) { |
| 411 | assert(reg.value_regs.size() == 1); |
| 412 | m_value_reg_offset_map[local_regnum] = reg.value_reg_offset; |
| 413 | } |
| 414 | |
| 415 | struct RegisterInfo reg_info { |
| 416 | .name: reg.name.AsCString(), .alt_name: reg.alt_name.AsCString(), .byte_size: reg.byte_size, |
| 417 | .byte_offset: reg.byte_offset, .encoding: reg.encoding, .format: reg.format, |
| 418 | .kinds: {reg.regnum_ehframe, reg.regnum_dwarf, reg.regnum_generic, |
| 419 | reg.regnum_remote, local_regnum}, |
| 420 | // value_regs and invalidate_regs are filled by Finalize() |
| 421 | .value_regs: nullptr, .invalidate_regs: nullptr, .flags_type: reg.flags_type |
| 422 | }; |
| 423 | |
| 424 | m_regs.push_back(x: reg_info); |
| 425 | |
| 426 | uint32_t set = GetRegisterSetIndexByName(set_name: reg.set_name, can_create: true); |
| 427 | assert(set < m_sets.size()); |
| 428 | assert(set < m_set_reg_nums.size()); |
| 429 | assert(set < m_set_names.size()); |
| 430 | m_set_reg_nums[set].push_back(x: local_regnum); |
| 431 | }; |
| 432 | |
| 433 | Finalize(arch); |
| 434 | return m_regs.size(); |
| 435 | } |
| 436 | |
| 437 | void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { |
| 438 | if (m_finalized) |
| 439 | return; |
| 440 | |
| 441 | m_finalized = true; |
| 442 | const size_t num_sets = m_sets.size(); |
| 443 | for (size_t set = 0; set < num_sets; ++set) { |
| 444 | assert(m_sets.size() == m_set_reg_nums.size()); |
| 445 | m_sets[set].num_registers = m_set_reg_nums[set].size(); |
| 446 | m_sets[set].registers = m_set_reg_nums[set].data(); |
| 447 | } |
| 448 | |
| 449 | // make sure value_regs are terminated with LLDB_INVALID_REGNUM |
| 450 | |
| 451 | for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), |
| 452 | end = m_value_regs_map.end(); |
| 453 | pos != end; ++pos) { |
| 454 | if (pos->second.back() != LLDB_INVALID_REGNUM) |
| 455 | pos->second.push_back(LLDB_INVALID_REGNUM); |
| 456 | } |
| 457 | |
| 458 | // Now update all value_regs with each register info as needed |
| 459 | const size_t num_regs = m_regs.size(); |
| 460 | for (size_t i = 0; i < num_regs; ++i) { |
| 461 | if (auto it = m_value_regs_map.find(x: i); it != m_value_regs_map.end()) |
| 462 | m_regs[i].value_regs = it->second.data(); |
| 463 | else |
| 464 | m_regs[i].value_regs = nullptr; |
| 465 | } |
| 466 | |
| 467 | // Expand all invalidation dependencies |
| 468 | for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), |
| 469 | end = m_invalidate_regs_map.end(); |
| 470 | pos != end; ++pos) { |
| 471 | const uint32_t reg_num = pos->first; |
| 472 | |
| 473 | if (m_regs[reg_num].value_regs) { |
| 474 | reg_num_collection ; |
| 475 | for (const uint32_t invalidate_reg_num : pos->second) { |
| 476 | reg_to_regs_map::iterator invalidate_pos = |
| 477 | m_invalidate_regs_map.find(x: invalidate_reg_num); |
| 478 | if (invalidate_pos != m_invalidate_regs_map.end()) { |
| 479 | for (const uint32_t concrete_invalidate_reg_num : |
| 480 | invalidate_pos->second) { |
| 481 | if (concrete_invalidate_reg_num != reg_num) |
| 482 | extra_invalid_regs.push_back(x: concrete_invalidate_reg_num); |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | pos->second.insert(position: pos->second.end(), first: extra_invalid_regs.begin(), |
| 487 | last: extra_invalid_regs.end()); |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | // sort and unique all invalidate registers and make sure each is terminated |
| 492 | // with LLDB_INVALID_REGNUM |
| 493 | for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), |
| 494 | end = m_invalidate_regs_map.end(); |
| 495 | pos != end; ++pos) { |
| 496 | if (pos->second.size() > 1) { |
| 497 | llvm::sort(C&: pos->second); |
| 498 | pos->second.erase(first: llvm::unique(R&: pos->second), last: pos->second.end()); |
| 499 | } |
| 500 | assert(!pos->second.empty()); |
| 501 | if (pos->second.back() != LLDB_INVALID_REGNUM) |
| 502 | pos->second.push_back(LLDB_INVALID_REGNUM); |
| 503 | } |
| 504 | |
| 505 | // Now update all invalidate_regs with each register info as needed |
| 506 | for (size_t i = 0; i < num_regs; ++i) { |
| 507 | if (auto it = m_invalidate_regs_map.find(x: i); |
| 508 | it != m_invalidate_regs_map.end()) |
| 509 | m_regs[i].invalidate_regs = it->second.data(); |
| 510 | else |
| 511 | m_regs[i].invalidate_regs = nullptr; |
| 512 | } |
| 513 | |
| 514 | // Check if we need to automatically set the generic registers in case they |
| 515 | // weren't set |
| 516 | bool generic_regs_specified = false; |
| 517 | for (const auto ® : m_regs) { |
| 518 | if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) { |
| 519 | generic_regs_specified = true; |
| 520 | break; |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | if (!generic_regs_specified) { |
| 525 | switch (arch.GetMachine()) { |
| 526 | case llvm::Triple::aarch64: |
| 527 | case llvm::Triple::aarch64_32: |
| 528 | case llvm::Triple::aarch64_be: |
| 529 | for (auto ® : m_regs) { |
| 530 | if (strcmp(s1: reg.name, s2: "pc" ) == 0) |
| 531 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
| 532 | else if ((strcmp(s1: reg.name, s2: "fp" ) == 0) || |
| 533 | (strcmp(s1: reg.name, s2: "x29" ) == 0)) |
| 534 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
| 535 | else if ((strcmp(s1: reg.name, s2: "lr" ) == 0) || |
| 536 | (strcmp(s1: reg.name, s2: "x30" ) == 0)) |
| 537 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; |
| 538 | else if ((strcmp(s1: reg.name, s2: "sp" ) == 0) || |
| 539 | (strcmp(s1: reg.name, s2: "x31" ) == 0)) |
| 540 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
| 541 | else if (strcmp(s1: reg.name, s2: "cpsr" ) == 0) |
| 542 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
| 543 | } |
| 544 | break; |
| 545 | |
| 546 | case llvm::Triple::arm: |
| 547 | case llvm::Triple::armeb: |
| 548 | case llvm::Triple::thumb: |
| 549 | case llvm::Triple::thumbeb: |
| 550 | for (auto ® : m_regs) { |
| 551 | if ((strcmp(s1: reg.name, s2: "pc" ) == 0) || (strcmp(s1: reg.name, s2: "r15" ) == 0)) |
| 552 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
| 553 | else if ((strcmp(s1: reg.name, s2: "sp" ) == 0) || |
| 554 | (strcmp(s1: reg.name, s2: "r13" ) == 0)) |
| 555 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
| 556 | else if ((strcmp(s1: reg.name, s2: "lr" ) == 0) || |
| 557 | (strcmp(s1: reg.name, s2: "r14" ) == 0)) |
| 558 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; |
| 559 | else if ((strcmp(s1: reg.name, s2: "r7" ) == 0) && |
| 560 | arch.GetTriple().getVendor() == llvm::Triple::Apple) |
| 561 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
| 562 | else if ((strcmp(s1: reg.name, s2: "r11" ) == 0) && |
| 563 | arch.GetTriple().getVendor() != llvm::Triple::Apple) |
| 564 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
| 565 | else if (strcmp(s1: reg.name, s2: "fp" ) == 0) |
| 566 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
| 567 | else if (strcmp(s1: reg.name, s2: "cpsr" ) == 0) |
| 568 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
| 569 | } |
| 570 | break; |
| 571 | |
| 572 | case llvm::Triple::x86: |
| 573 | for (auto ® : m_regs) { |
| 574 | if ((strcmp(s1: reg.name, s2: "eip" ) == 0) || (strcmp(s1: reg.name, s2: "pc" ) == 0)) |
| 575 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
| 576 | else if ((strcmp(s1: reg.name, s2: "esp" ) == 0) || |
| 577 | (strcmp(s1: reg.name, s2: "sp" ) == 0)) |
| 578 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
| 579 | else if ((strcmp(s1: reg.name, s2: "ebp" ) == 0) || |
| 580 | (strcmp(s1: reg.name, s2: "fp" ) == 0)) |
| 581 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
| 582 | else if ((strcmp(s1: reg.name, s2: "eflags" ) == 0) || |
| 583 | (strcmp(s1: reg.name, s2: "flags" ) == 0)) |
| 584 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
| 585 | } |
| 586 | break; |
| 587 | |
| 588 | case llvm::Triple::x86_64: |
| 589 | for (auto ® : m_regs) { |
| 590 | if ((strcmp(s1: reg.name, s2: "rip" ) == 0) || (strcmp(s1: reg.name, s2: "pc" ) == 0)) |
| 591 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; |
| 592 | else if ((strcmp(s1: reg.name, s2: "rsp" ) == 0) || |
| 593 | (strcmp(s1: reg.name, s2: "sp" ) == 0)) |
| 594 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; |
| 595 | else if ((strcmp(s1: reg.name, s2: "rbp" ) == 0) || |
| 596 | (strcmp(s1: reg.name, s2: "fp" ) == 0)) |
| 597 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; |
| 598 | else if ((strcmp(s1: reg.name, s2: "rflags" ) == 0) || |
| 599 | (strcmp(s1: reg.name, s2: "eflags" ) == 0) || |
| 600 | (strcmp(s1: reg.name, s2: "flags" ) == 0)) |
| 601 | reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; |
| 602 | } |
| 603 | break; |
| 604 | |
| 605 | default: |
| 606 | break; |
| 607 | } |
| 608 | } |
| 609 | |
| 610 | // At this stage call ConfigureOffsets to calculate register offsets for |
| 611 | // targets supporting dynamic offset calculation. It also calculates |
| 612 | // total byte size of register data. |
| 613 | ConfigureOffsets(); |
| 614 | |
| 615 | // Check if register info is reconfigurable |
| 616 | // AArch64 SVE register set has configurable register sizes, as does the ZA |
| 617 | // register that SME added (the streaming state of SME reuses the SVE state). |
| 618 | if (arch.GetTriple().isAArch64()) { |
| 619 | for (const auto ® : m_regs) { |
| 620 | if ((strcmp(s1: reg.name, s2: "vg" ) == 0) || (strcmp(s1: reg.name, s2: "svg" ) == 0)) { |
| 621 | m_is_reconfigurable = true; |
| 622 | break; |
| 623 | } |
| 624 | } |
| 625 | } |
| 626 | } |
| 627 | |
| 628 | void DynamicRegisterInfo::ConfigureOffsets() { |
| 629 | // We are going to create a map between remote (eRegisterKindProcessPlugin) |
| 630 | // and local (eRegisterKindLLDB) register numbers. This map will give us |
| 631 | // remote register numbers in increasing order for offset calculation. |
| 632 | std::map<uint32_t, uint32_t> remote_to_local_regnum_map; |
| 633 | for (const auto ® : m_regs) |
| 634 | remote_to_local_regnum_map[reg.kinds[eRegisterKindProcessPlugin]] = |
| 635 | reg.kinds[eRegisterKindLLDB]; |
| 636 | |
| 637 | // At this stage we manually calculate g/G packet offsets of all primary |
| 638 | // registers, only if target XML or qRegisterInfo packet did not send |
| 639 | // an offset explicitly. |
| 640 | uint32_t reg_offset = 0; |
| 641 | for (auto const ®num_pair : remote_to_local_regnum_map) { |
| 642 | if (m_regs[regnum_pair.second].byte_offset == LLDB_INVALID_INDEX32 && |
| 643 | m_regs[regnum_pair.second].value_regs == nullptr) { |
| 644 | m_regs[regnum_pair.second].byte_offset = reg_offset; |
| 645 | |
| 646 | reg_offset = m_regs[regnum_pair.second].byte_offset + |
| 647 | m_regs[regnum_pair.second].byte_size; |
| 648 | } |
| 649 | } |
| 650 | |
| 651 | // Now update all value_regs with each register info as needed |
| 652 | for (auto ® : m_regs) { |
| 653 | if (reg.value_regs != nullptr) { |
| 654 | // Assign a valid offset to all pseudo registers that have only a single |
| 655 | // parent register in value_regs list, if not assigned by stub. Pseudo |
| 656 | // registers with value_regs list populated will share same offset as |
| 657 | // that of their corresponding parent register. |
| 658 | if (reg.byte_offset == LLDB_INVALID_INDEX32) { |
| 659 | uint32_t value_regnum = reg.value_regs[0]; |
| 660 | if (value_regnum != LLDB_INVALID_INDEX32 && |
| 661 | reg.value_regs[1] == LLDB_INVALID_INDEX32) { |
| 662 | reg.byte_offset = |
| 663 | GetRegisterInfoAtIndex(i: value_regnum)->byte_offset; |
| 664 | auto it = m_value_reg_offset_map.find(x: reg.kinds[eRegisterKindLLDB]); |
| 665 | if (it != m_value_reg_offset_map.end()) |
| 666 | reg.byte_offset += it->second; |
| 667 | } |
| 668 | } |
| 669 | } |
| 670 | |
| 671 | reg_offset = reg.byte_offset + reg.byte_size; |
| 672 | if (m_reg_data_byte_size < reg_offset) |
| 673 | m_reg_data_byte_size = reg_offset; |
| 674 | } |
| 675 | } |
| 676 | |
| 677 | bool DynamicRegisterInfo::IsReconfigurable() { return m_is_reconfigurable; } |
| 678 | |
| 679 | size_t DynamicRegisterInfo::GetNumRegisters() const { return m_regs.size(); } |
| 680 | |
| 681 | size_t DynamicRegisterInfo::GetNumRegisterSets() const { return m_sets.size(); } |
| 682 | |
| 683 | size_t DynamicRegisterInfo::GetRegisterDataByteSize() const { |
| 684 | return m_reg_data_byte_size; |
| 685 | } |
| 686 | |
| 687 | const RegisterInfo * |
| 688 | DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) const { |
| 689 | if (i < m_regs.size()) |
| 690 | return &m_regs[i]; |
| 691 | return nullptr; |
| 692 | } |
| 693 | |
| 694 | const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind, |
| 695 | uint32_t num) const { |
| 696 | uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num); |
| 697 | if (reg_index != LLDB_INVALID_REGNUM) |
| 698 | return &m_regs[reg_index]; |
| 699 | return nullptr; |
| 700 | } |
| 701 | |
| 702 | const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const { |
| 703 | if (i < m_sets.size()) |
| 704 | return &m_sets[i]; |
| 705 | return nullptr; |
| 706 | } |
| 707 | |
| 708 | uint32_t |
| 709 | DynamicRegisterInfo::GetRegisterSetIndexByName(const ConstString &set_name, |
| 710 | bool can_create) { |
| 711 | name_collection::iterator pos, end = m_set_names.end(); |
| 712 | for (pos = m_set_names.begin(); pos != end; ++pos) { |
| 713 | if (*pos == set_name) |
| 714 | return std::distance(first: m_set_names.begin(), last: pos); |
| 715 | } |
| 716 | |
| 717 | m_set_names.push_back(x: set_name); |
| 718 | m_set_reg_nums.resize(new_size: m_set_reg_nums.size() + 1); |
| 719 | RegisterSet new_set = {.name: set_name.AsCString(), .short_name: nullptr, .num_registers: 0, .registers: nullptr}; |
| 720 | m_sets.push_back(x: new_set); |
| 721 | return m_sets.size() - 1; |
| 722 | } |
| 723 | |
| 724 | uint32_t |
| 725 | DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber(uint32_t kind, |
| 726 | uint32_t num) const { |
| 727 | reg_collection::const_iterator pos, end = m_regs.end(); |
| 728 | for (pos = m_regs.begin(); pos != end; ++pos) { |
| 729 | if (pos->kinds[kind] == num) |
| 730 | return std::distance(first: m_regs.begin(), last: pos); |
| 731 | } |
| 732 | |
| 733 | return LLDB_INVALID_REGNUM; |
| 734 | } |
| 735 | |
| 736 | void DynamicRegisterInfo::Clear() { |
| 737 | m_regs.clear(); |
| 738 | m_sets.clear(); |
| 739 | m_set_reg_nums.clear(); |
| 740 | m_set_names.clear(); |
| 741 | m_value_regs_map.clear(); |
| 742 | m_invalidate_regs_map.clear(); |
| 743 | m_reg_data_byte_size = 0; |
| 744 | m_finalized = false; |
| 745 | } |
| 746 | |
| 747 | void DynamicRegisterInfo::Dump() const { |
| 748 | StreamFile s(stdout, false); |
| 749 | const size_t num_regs = m_regs.size(); |
| 750 | s.Printf(format: "%p: DynamicRegisterInfo contains %" PRIu64 " registers:\n" , |
| 751 | static_cast<const void *>(this), static_cast<uint64_t>(num_regs)); |
| 752 | for (size_t i = 0; i < num_regs; ++i) { |
| 753 | s.Printf(format: "[%3" PRIu64 "] name = %-10s" , (uint64_t)i, m_regs[i].name); |
| 754 | s.Printf(format: ", size = %2u, offset = %4u, encoding = %u, format = %-10s" , |
| 755 | m_regs[i].byte_size, m_regs[i].byte_offset, m_regs[i].encoding, |
| 756 | FormatManager::GetFormatAsCString(format: m_regs[i].format)); |
| 757 | if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM) |
| 758 | s.Printf(format: ", process plugin = %3u" , |
| 759 | m_regs[i].kinds[eRegisterKindProcessPlugin]); |
| 760 | if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) |
| 761 | s.Printf(format: ", dwarf = %3u" , m_regs[i].kinds[eRegisterKindDWARF]); |
| 762 | if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) |
| 763 | s.Printf(format: ", ehframe = %3u" , m_regs[i].kinds[eRegisterKindEHFrame]); |
| 764 | if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) |
| 765 | s.Printf(format: ", generic = %3u" , m_regs[i].kinds[eRegisterKindGeneric]); |
| 766 | if (m_regs[i].alt_name) |
| 767 | s.Printf(format: ", alt-name = %s" , m_regs[i].alt_name); |
| 768 | if (m_regs[i].value_regs) { |
| 769 | s.Printf(format: ", value_regs = [ " ); |
| 770 | for (size_t j = 0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j) { |
| 771 | s.Printf(format: "%s " , m_regs[m_regs[i].value_regs[j]].name); |
| 772 | } |
| 773 | s.Printf(format: "]" ); |
| 774 | } |
| 775 | if (m_regs[i].invalidate_regs) { |
| 776 | s.Printf(format: ", invalidate_regs = [ " ); |
| 777 | for (size_t j = 0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; |
| 778 | ++j) { |
| 779 | s.Printf(format: "%s " , m_regs[m_regs[i].invalidate_regs[j]].name); |
| 780 | } |
| 781 | s.Printf(format: "]" ); |
| 782 | } |
| 783 | s.EOL(); |
| 784 | } |
| 785 | |
| 786 | const size_t num_sets = m_sets.size(); |
| 787 | s.Printf(format: "%p: DynamicRegisterInfo contains %" PRIu64 " register sets:\n" , |
| 788 | static_cast<const void *>(this), static_cast<uint64_t>(num_sets)); |
| 789 | for (size_t i = 0; i < num_sets; ++i) { |
| 790 | s.Printf(format: "set[%" PRIu64 "] name = %s, regs = [" , (uint64_t)i, |
| 791 | m_sets[i].name); |
| 792 | for (size_t idx = 0; idx < m_sets[i].num_registers; ++idx) { |
| 793 | s.Printf(format: "%s " , m_regs[m_sets[i].registers[idx]].name); |
| 794 | } |
| 795 | s.Printf(format: "]\n" ); |
| 796 | } |
| 797 | } |
| 798 | |
| 799 | const lldb_private::RegisterInfo * |
| 800 | DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) const { |
| 801 | for (auto ®_info : m_regs) |
| 802 | if (reg_info.name == reg_name) |
| 803 | return ®_info; |
| 804 | return nullptr; |
| 805 | } |
| 806 | |
| 807 | void lldb_private::addSupplementaryRegister( |
| 808 | std::vector<DynamicRegisterInfo::Register> ®s, |
| 809 | DynamicRegisterInfo::Register new_reg_info) { |
| 810 | assert(!new_reg_info.value_regs.empty()); |
| 811 | const uint32_t reg_num = regs.size(); |
| 812 | regs.push_back(x: new_reg_info); |
| 813 | |
| 814 | std::map<uint32_t, std::vector<uint32_t>> new_invalidates; |
| 815 | for (uint32_t value_reg : new_reg_info.value_regs) { |
| 816 | // copy value_regs to invalidate_regs |
| 817 | new_invalidates[reg_num].push_back(x: value_reg); |
| 818 | |
| 819 | // copy invalidate_regs from the parent register |
| 820 | llvm::append_range(C&: new_invalidates[reg_num], |
| 821 | R&: regs[value_reg].invalidate_regs); |
| 822 | |
| 823 | // add reverse invalidate entries |
| 824 | for (uint32_t x : new_invalidates[reg_num]) |
| 825 | new_invalidates[x].push_back(x: reg_num); |
| 826 | } |
| 827 | |
| 828 | for (const auto &x : new_invalidates) |
| 829 | llvm::append_range(C&: regs[x.first].invalidate_regs, R: x.second); |
| 830 | } |
| 831 | |