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
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
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
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
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
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
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
360static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
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
368static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
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 <= m_reg_info.last_gpr; // GPR's come first.
378}
379
381 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
382}
383
385 return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.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 switch (register_info->GetTargetArchitecture().GetMachine()) {
403 case llvm::Triple::x86:
421 break;
422 case llvm::Triple::x86_64:
440 break;
441 default:
442 assert(false && "Unhandled target architecture.");
443 break;
444 }
445
446 ::memset(&m_fpr, 0, sizeof(FPR));
447 ::memset(&m_ymm_set, 0, sizeof(YMM));
448
450}
451
453
455 if (m_fpr_type == eNotValid) {
456 // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
457 m_fpr_type = eXSAVE; // extended floating-point registers, if available
458 if (!ReadFPR())
459 m_fpr_type = eFXSAVE; // assume generic floating-point registers
460 }
461 return m_fpr_type;
462}
463
465
467
469 assert(reg < m_reg_info.num_registers && "Invalid register number.");
470 return GetRegisterInfo()[reg].byte_offset;
471}
472
474 assert(reg < m_reg_info.num_registers && "Invalid register number.");
475 return GetRegisterInfo()[reg].byte_size;
476}
477
479 size_t num_registers =
481 if (GetFPRType() == eXSAVE)
482 return num_registers + m_reg_info.num_avx_registers;
483 return num_registers;
484}
485
487 return m_register_info_up->GetGPRSize();
488}
489
491 return GetRegisterInfo()[m_reg_info.first_fpr].byte_offset;
492}
493
495 // Commonly, this method is overridden and g_register_infos is copied and
496 // specialized. So, use GetRegisterInfo() rather than g_register_infos in
497 // this scope.
498 return m_register_info_up->GetRegisterInfo();
499}
500
501const RegisterInfo *
503 if (reg < m_reg_info.num_registers)
504 return &GetRegisterInfo()[reg];
505 else
506 return nullptr;
507}
508
510 size_t sets = 0;
511 for (size_t set = 0; set < k_num_register_sets; ++set) {
512 if (IsRegisterSetAvailable(set))
513 ++sets;
514 }
515
516 return sets;
517}
518
519const RegisterSet *RegisterContextPOSIX_x86::GetRegisterSet(size_t set) {
520 if (IsRegisterSetAvailable(set)) {
521 switch (m_register_info_up->GetTargetArchitecture().GetMachine()) {
522 case llvm::Triple::x86:
523 return &g_reg_sets_i386[set];
524 case llvm::Triple::x86_64:
525 return &g_reg_sets_x86_64[set];
526 default:
527 assert(false && "Unhandled target architecture.");
528 return nullptr;
529 }
530 }
531 return nullptr;
532}
533
535 assert(reg < m_reg_info.num_registers && "Invalid register offset.");
536 return GetRegisterInfo()[reg].name;
537}
538
539// Parse ymm registers and into xmm.bytes and ymmh.bytes.
541 lldb::ByteOrder byte_order) {
542 if (!IsAVX(reg))
543 return false;
544
545 if (byte_order == eByteOrderLittle) {
546 uint32_t reg_no = reg - m_reg_info.first_ymm;
547 YMMToXState(m_ymm_set.ymm[reg_no],
548 m_fpr.fxsave.xmm[reg_no].bytes,
549 m_fpr.xsave.ymmh[reg_no].bytes);
550 return true;
551 }
552
553 return false; // unsupported or invalid byte order
554}
555
556// Concatenate xmm.bytes with ymmh.bytes
558 lldb::ByteOrder byte_order) {
559 if (!IsAVX(reg))
560 return false;
561
562 if (byte_order == eByteOrderLittle) {
563 uint32_t reg_no = reg - m_reg_info.first_ymm;
564 m_ymm_set.ymm[reg_no] = XStateToYMM(
565 m_fpr.fxsave.xmm[reg_no].bytes,
566 m_fpr.xsave.ymmh[reg_no].bytes);
567 return true;
568 }
569
570 return false; // unsupported or invalid byte order
571}
572
574 // Note: Extended register sets are assumed to be at the end of g_reg_sets...
576
577 if (GetFPRType() == eXSAVE) // ...and to start with AVX registers.
578 ++num_sets;
579 return (set_index < num_sets);
580}
constexpr size_t k_num_register_sets
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[]
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[]
@ k_num_extended_register_sets
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)
const char * GetRegisterName(unsigned reg)
bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:678
RegisterInfo interface to patch RegisterInfo structure for archs.
const lldb_private::ArchSpec & GetTargetArchitecture() const
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:79
A class that represents a running process on the host machine.
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