LLDB mainline
RegisterContextPOSIX_x86.cpp
Go to the documentation of this file.
1//===-- RegisterContextPOSIX_x86.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 <cerrno>
10#include <cstdint>
11#include <cstring>
12
13#include "lldb/Target/Process.h"
14#include "lldb/Target/Target.h"
15#include "lldb/Target/Thread.h"
18#include "lldb/Utility/Endian.h"
20#include "lldb/Utility/Scalar.h"
21#include "llvm/Support/Compiler.h"
22
24#include "RegisterContext_x86.h"
25
26using namespace lldb_private;
27using namespace lldb;
28
29const uint32_t g_gpr_regnums_i386[] = {
38 LLDB_INVALID_REGNUM, // Register sets must be terminated with
39 // LLDB_INVALID_REGNUM.
40};
41static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
42 1 ==
44 "g_gpr_regnums_i386 has wrong number of register infos");
45
46const uint32_t g_lldb_regnums_i386[] = {
56 LLDB_INVALID_REGNUM // Register sets must be terminated with
57 // LLDB_INVALID_REGNUM.
58};
59static_assert((sizeof(g_lldb_regnums_i386) / sizeof(g_lldb_regnums_i386[0])) -
60 1 ==
62 "g_lldb_regnums_i386 has wrong number of register infos");
63
64const uint32_t g_avx_regnums_i386[] = {
67 LLDB_INVALID_REGNUM // Register sets must be terminated with
68 // LLDB_INVALID_REGNUM.
69};
70static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
71 1 ==
73 " g_avx_regnums_i386 has wrong number of register infos");
74
75static const uint32_t g_gpr_regnums_x86_64[] = {
84 lldb_r8d_x86_64, // Low 32 bits or r8
85 lldb_r9d_x86_64, // Low 32 bits or r9
86 lldb_r10d_x86_64, // Low 32 bits or r10
87 lldb_r11d_x86_64, // Low 32 bits or r11
88 lldb_r12d_x86_64, // Low 32 bits or r12
89 lldb_r13d_x86_64, // Low 32 bits or r13
90 lldb_r14d_x86_64, // Low 32 bits or r14
91 lldb_r15d_x86_64, // Low 32 bits or r15
94 lldb_r8w_x86_64, // Low 16 bits or r8
95 lldb_r9w_x86_64, // Low 16 bits or r9
96 lldb_r10w_x86_64, // Low 16 bits or r10
97 lldb_r11w_x86_64, // Low 16 bits or r11
98 lldb_r12w_x86_64, // Low 16 bits or r12
99 lldb_r13w_x86_64, // Low 16 bits or r13
100 lldb_r14w_x86_64, // Low 16 bits or r14
101 lldb_r15w_x86_64, // Low 16 bits or r15
105 lldb_r8l_x86_64, // Low 8 bits or r8
106 lldb_r9l_x86_64, // Low 8 bits or r9
107 lldb_r10l_x86_64, // Low 8 bits or r10
108 lldb_r11l_x86_64, // Low 8 bits or r11
109 lldb_r12l_x86_64, // Low 8 bits or r12
110 lldb_r13l_x86_64, // Low 8 bits or r13
111 lldb_r14l_x86_64, // Low 8 bits or r14
112 lldb_r15l_x86_64, // Low 8 bits or r15
113 LLDB_INVALID_REGNUM // Register sets must be terminated with
114 // LLDB_INVALID_REGNUM.
115};
116static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
117 1 ==
119 "g_gpr_regnums_x86_64 has wrong number of register infos");
120
121static const uint32_t g_lldb_regnums_x86_64[] = {
137 LLDB_INVALID_REGNUM // Register sets must be terminated with
138 // LLDB_INVALID_REGNUM.
139};
140static_assert((sizeof(g_lldb_regnums_x86_64) /
141 sizeof(g_lldb_regnums_x86_64[0])) -
142 1 ==
144 "g_lldb_regnums_x86_64 has wrong number of register infos");
145
146static const uint32_t g_avx_regnums_x86_64[] = {
151 LLDB_INVALID_REGNUM // Register sets must be terminated with
152 // LLDB_INVALID_REGNUM.
153};
154static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
155 1 ==
157 "g_avx_regnums_x86_64 has wrong number of register infos");
158
175
196
229
278
283
288
305
322
339
356
357// Number of register sets provided by this context.
359
361 {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
363 {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
365 {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
367
369 {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
371 {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
373 {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
375
377 return reg <= GetRegInfo().last_gpr; // GPR's come first.
378}
379
381 return (GetRegInfo().first_fpr <= reg && reg <= GetRegInfo().last_fpr);
382}
383
385 return (GetRegInfo().first_ymm <= reg && reg <= GetRegInfo().last_ymm);
386}
387
388bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type) {
389 bool generic_fpr = IsFPR(reg);
390
391 if (fpr_type == eXSAVE)
392 return generic_fpr || IsAVX(reg);
393 return generic_fpr;
394}
395
397 Thread &thread, uint32_t concrete_frame_idx,
398 RegisterInfoInterface *register_info)
399 : RegisterContext(thread, concrete_frame_idx) {
400 m_register_info_up.reset(register_info);
401
402 ::memset(&m_fpr, 0, sizeof(FPR));
403 ::memset(&m_ymm_set, 0, sizeof(YMM));
404
406}
407
409
411 if (m_fpr_type == eNotValid) {
412 // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
413 m_fpr_type = eXSAVE; // extended floating-point registers, if available
414 if (!ReadFPR())
415 m_fpr_type = eFXSAVE; // assume generic floating-point registers
416 }
417 return m_fpr_type;
418}
419
421
423
425 assert(reg < GetRegInfo().num_registers && "Invalid register number.");
426 return GetRegisterInfo()[reg].byte_offset;
427}
428
430 return GetRegInfoShared(
431 m_register_info_up->GetTargetArchitecture().GetMachine(),
432 /*with_base=*/false);
433}
434
436 assert(reg < GetRegInfo().num_registers && "Invalid register number.");
437 return GetRegisterInfo()[reg].byte_size;
438}
439
441 size_t num_registers =
443 if (GetFPRType() == eXSAVE)
444 return num_registers + GetRegInfo().num_avx_registers;
445 return num_registers;
446}
447
449 return m_register_info_up->GetGPRSize();
450}
451
454}
455
457 // Commonly, this method is overridden and g_register_infos is copied and
458 // specialized. So, use GetRegisterInfo() rather than g_register_infos in
459 // this scope.
460 return m_register_info_up->GetRegisterInfo();
461}
462
463const RegisterInfo *
465 if (reg < GetRegInfo().num_registers)
466 return &GetRegisterInfo()[reg];
467 else
468 return nullptr;
469}
470
472 size_t sets = 0;
473 for (size_t set = 0; set < k_num_register_sets; ++set) {
474 if (IsRegisterSetAvailable(set))
475 ++sets;
476 }
477
478 return sets;
479}
480
482 if (IsRegisterSetAvailable(set)) {
483 switch (m_register_info_up->GetTargetArchitecture().GetMachine()) {
484 case llvm::Triple::x86:
485 return &g_reg_sets_i386[set];
486 case llvm::Triple::x86_64:
487 return &g_reg_sets_x86_64[set];
488 default:
489 assert(false && "Unhandled target architecture.");
490 return nullptr;
491 }
492 }
493 return nullptr;
494}
495
497 assert(reg < GetRegInfo().num_registers && "Invalid register offset.");
498 return GetRegisterInfo()[reg].name;
499}
500
501// Parse ymm registers and into xmm.bytes and ymmh.bytes.
503 lldb::ByteOrder byte_order) {
504 if (!IsAVX(reg))
505 return false;
506
507 if (byte_order == eByteOrderLittle) {
508 uint32_t reg_no = reg - GetRegInfo().first_ymm;
509 YMMToXState(m_ymm_set.ymm[reg_no], m_fpr.fxsave.xmm[reg_no].bytes,
510 m_fpr.xsave.ymmh[reg_no].bytes);
511 return true;
512 }
513
514 return false; // unsupported or invalid byte order
515}
516
517// Concatenate xmm.bytes with ymmh.bytes
519 lldb::ByteOrder byte_order) {
520 if (!IsAVX(reg))
521 return false;
522
523 if (byte_order == eByteOrderLittle) {
524 uint32_t reg_no = reg - GetRegInfo().first_ymm;
525 m_ymm_set.ymm[reg_no] = XStateToYMM(m_fpr.fxsave.xmm[reg_no].bytes,
526 m_fpr.xsave.ymmh[reg_no].bytes);
527 return true;
528 }
529
530 return false; // unsupported or invalid byte order
531}
532
534 // Note: Extended register sets are assumed to be at the end of g_reg_sets...
536
537 if (GetFPRType() == eXSAVE) // ...and to start with AVX registers.
538 ++num_sets;
539 return (set_index < num_sets);
540}
constexpr size_t k_num_register_sets
static const RegisterSet g_reg_sets_i386[]
static const RegisterSet g_reg_sets_x86_64[]
const uint32_t g_lldb_regnums_i386[]
static const uint32_t g_gpr_regnums_x86_64[]
static const RegisterSet g_reg_sets_i386[k_num_register_sets]
static const uint32_t g_lldb_regnums_x86_64[]
@ k_num_extended_register_sets
const uint32_t g_gpr_regnums_i386[]
static const RegisterSet g_reg_sets_x86_64[k_num_register_sets]
const uint32_t g_avx_regnums_i386[]
static const uint32_t g_avx_regnums_x86_64[]
std::unique_ptr< lldb_private::RegisterInfoInterface > m_register_info_up
~RegisterContextPOSIX_x86() override
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
virtual unsigned GetRegisterOffset(unsigned reg)
virtual bool IsRegisterSetAvailable(size_t set_index)
virtual bool ReadFPR()=0
const lldb_private::RegisterSet * GetRegisterSet(size_t set) override
virtual const lldb_private::RegisterInfo * GetRegisterInfo()
RegisterContextPOSIX_x86(lldb_private::Thread &thread, uint32_t concrete_frame_idx, lldb_private::RegisterInfoInterface *register_info)
virtual unsigned GetRegisterSize(unsigned reg)
virtual lldb_private::RegInfo & GetRegInfo()
const char * GetRegisterName(unsigned reg)
bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
RegisterInfo interface to patch RegisterInfo structure for archs.
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
A class that represents a running process on the host machine.
RegInfo & GetRegInfoShared(llvm::Triple::ArchType arch_type, bool with_base)
void YMMToXState(const YMMReg &input, void *xmm_bytes, void *ymmh_bytes)
YMMReg XStateToYMM(const void *xmm_bytes, const void *ymmh_bytes)
Definition: SBAddress.h:15
ByteOrder
Byte ordering definitions.
@ eByteOrderLittle
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.