180814287SRaphael Isemann //===-- RegisterContextLinux_x86_64.cpp -----------------------------------===//
23e699d41SVirgile Bello //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63e699d41SVirgile Bello //
73e699d41SVirgile Bello //===---------------------------------------------------------------------===//
83e699d41SVirgile Bello
93e699d41SVirgile Bello #include "RegisterContextLinux_x86_64.h"
10b9c1b51eSKate Stone #include "RegisterContextLinux_i386.h"
11b9c1b51eSKate Stone #include "RegisterContextPOSIX_x86.h"
12b9c1b51eSKate Stone #include <vector>
133e699d41SVirgile Bello
143e699d41SVirgile Bello using namespace lldb_private;
153e699d41SVirgile Bello using namespace lldb;
163e699d41SVirgile Bello
17b9c1b51eSKate Stone typedef struct _GPR {
183e699d41SVirgile Bello uint64_t r15;
193e699d41SVirgile Bello uint64_t r14;
203e699d41SVirgile Bello uint64_t r13;
213e699d41SVirgile Bello uint64_t r12;
223e699d41SVirgile Bello uint64_t rbp;
233e699d41SVirgile Bello uint64_t rbx;
243e699d41SVirgile Bello uint64_t r11;
253e699d41SVirgile Bello uint64_t r10;
263e699d41SVirgile Bello uint64_t r9;
273e699d41SVirgile Bello uint64_t r8;
283e699d41SVirgile Bello uint64_t rax;
293e699d41SVirgile Bello uint64_t rcx;
303e699d41SVirgile Bello uint64_t rdx;
313e699d41SVirgile Bello uint64_t rsi;
323e699d41SVirgile Bello uint64_t rdi;
334778e410SRavitheja Addepally uint64_t orig_rax;
343e699d41SVirgile Bello uint64_t rip;
353e699d41SVirgile Bello uint64_t cs;
363e699d41SVirgile Bello uint64_t rflags;
373e699d41SVirgile Bello uint64_t rsp;
383e699d41SVirgile Bello uint64_t ss;
393e699d41SVirgile Bello uint64_t fs_base;
403e699d41SVirgile Bello uint64_t gs_base;
413e699d41SVirgile Bello uint64_t ds;
423e699d41SVirgile Bello uint64_t es;
433e699d41SVirgile Bello uint64_t fs;
443e699d41SVirgile Bello uint64_t gs;
453e699d41SVirgile Bello } GPR;
463e699d41SVirgile Bello
474ced470aSChaoren Lin struct DBG {
484ced470aSChaoren Lin uint64_t dr[8];
494ced470aSChaoren Lin };
504ced470aSChaoren Lin
51b9c1b51eSKate Stone struct UserArea {
523e699d41SVirgile Bello GPR gpr; // General purpose registers.
533e699d41SVirgile Bello int32_t fpvalid; // True if FPU is being used.
543e699d41SVirgile Bello int32_t pad0;
55b9c1b51eSKate Stone FXSAVE fpr; // General purpose floating point registers (see FPR for extended
56b9c1b51eSKate Stone // register sets).
573e699d41SVirgile Bello uint64_t tsize; // Text segment size.
583e699d41SVirgile Bello uint64_t dsize; // Data segment size.
593e699d41SVirgile Bello uint64_t ssize; // Stack segment size.
603e699d41SVirgile Bello uint64_t start_code; // VM address of text.
613e699d41SVirgile Bello uint64_t start_stack; // VM address of stack bottom (top in rsp).
623e699d41SVirgile Bello int64_t signal; // Signal causing core dump.
633e699d41SVirgile Bello int32_t reserved; // Unused.
643e699d41SVirgile Bello int32_t pad1;
653e699d41SVirgile Bello uint64_t ar0; // Location of GPR's.
663e699d41SVirgile Bello FXSAVE *fpstate; // Location of FPR's.
673e699d41SVirgile Bello uint64_t magic; // Identifier for core dumps.
683e699d41SVirgile Bello char u_comm[32]; // Command causing core dump.
694ced470aSChaoren Lin DBG dbg; // Debug registers.
703e699d41SVirgile Bello uint64_t error_code; // CPU error code.
713e699d41SVirgile Bello uint64_t fault_address; // Control register CR3.
723e699d41SVirgile Bello };
733e699d41SVirgile Bello
744b1063c7SEd Maste #define DR_OFFSET(reg_index) \
754b1063c7SEd Maste (LLVM_EXTENSION offsetof(UserArea, dbg) + \
764b1063c7SEd Maste LLVM_EXTENSION offsetof(DBG, dr[reg_index]))
774b1063c7SEd Maste
78b9c1b51eSKate Stone // Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64
79b9c1b51eSKate Stone // structure.
803e699d41SVirgile Bello #define DECLARE_REGISTER_INFOS_X86_64_STRUCT
813e699d41SVirgile Bello #include "RegisterInfos_x86_64.h"
823e699d41SVirgile Bello #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
833e699d41SVirgile Bello
GetPrivateRegisterInfoVector()84b9c1b51eSKate Stone static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {
85af245d11STodd Fiala static std::vector<lldb_private::RegisterInfo> g_register_infos;
86af245d11STodd Fiala return g_register_infos;
87af245d11STodd Fiala }
88af245d11STodd Fiala
893e699d41SVirgile Bello static const RegisterInfo *
GetRegisterInfo_i386(const lldb_private::ArchSpec & arch)90b9c1b51eSKate Stone GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {
91b9c1b51eSKate Stone std::vector<lldb_private::RegisterInfo> &g_register_infos =
92b9c1b51eSKate Stone GetPrivateRegisterInfoVector();
933e699d41SVirgile Bello
943e699d41SVirgile Bello // Allocate RegisterInfo only once
95b9c1b51eSKate Stone if (g_register_infos.empty()) {
963e699d41SVirgile Bello // Copy the register information from base class
97b9c1b51eSKate Stone std::unique_ptr<RegisterContextLinux_i386> reg_interface(
98b9c1b51eSKate Stone new RegisterContextLinux_i386(arch));
993e699d41SVirgile Bello const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
100b9c1b51eSKate Stone g_register_infos.insert(g_register_infos.end(), &base_info[0],
101b9c1b51eSKate Stone &base_info[k_num_registers_i386]);
1023e699d41SVirgile Bello
1033e699d41SVirgile Bello // Include RegisterInfos_x86_64 to update the g_register_infos structure
1043e699d41SVirgile Bello // with x86_64 offsets.
1053e699d41SVirgile Bello #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
1063e699d41SVirgile Bello #include "RegisterInfos_x86_64.h"
1073e699d41SVirgile Bello #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
1083e699d41SVirgile Bello }
1093e699d41SVirgile Bello
1103e699d41SVirgile Bello return &g_register_infos[0];
1113e699d41SVirgile Bello }
1123e699d41SVirgile Bello
GetRegisterInfoPtr(const ArchSpec & target_arch)113b9c1b51eSKate Stone static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) {
114b9c1b51eSKate Stone switch (target_arch.GetMachine()) {
115af245d11STodd Fiala case llvm::Triple::x86:
116af245d11STodd Fiala return GetRegisterInfo_i386(target_arch);
117af245d11STodd Fiala case llvm::Triple::x86_64:
118af245d11STodd Fiala return g_register_infos_x86_64;
119af245d11STodd Fiala default:
120af245d11STodd Fiala assert(false && "Unhandled target architecture.");
121af245d11STodd Fiala return nullptr;
122af245d11STodd Fiala }
1233e699d41SVirgile Bello }
1243e699d41SVirgile Bello
GetRegisterInfoCount(const ArchSpec & target_arch)125b9c1b51eSKate Stone static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) {
126b9c1b51eSKate Stone switch (target_arch.GetMachine()) {
127b9c1b51eSKate Stone case llvm::Triple::x86: {
128b9c1b51eSKate Stone assert(!GetPrivateRegisterInfoVector().empty() &&
129b9c1b51eSKate Stone "i386 register info not yet filled.");
130af245d11STodd Fiala return static_cast<uint32_t>(GetPrivateRegisterInfoVector().size());
131af245d11STodd Fiala }
132af245d11STodd Fiala case llvm::Triple::x86_64:
133b9c1b51eSKate Stone return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) /
134b9c1b51eSKate Stone sizeof(g_register_infos_x86_64[0]));
135af245d11STodd Fiala default:
136af245d11STodd Fiala assert(false && "Unhandled target architecture.");
137af245d11STodd Fiala return 0;
138af245d11STodd Fiala }
139af245d11STodd Fiala }
140af245d11STodd Fiala
GetUserRegisterInfoCount(const ArchSpec & target_arch)141b9c1b51eSKate Stone static uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch) {
142b9c1b51eSKate Stone switch (target_arch.GetMachine()) {
143d40ef999SVince Harron case llvm::Triple::x86:
144d40ef999SVince Harron return static_cast<uint32_t>(k_num_user_registers_i386);
145d40ef999SVince Harron case llvm::Triple::x86_64:
146d40ef999SVince Harron return static_cast<uint32_t>(k_num_user_registers_x86_64);
147d40ef999SVince Harron default:
148d40ef999SVince Harron assert(false && "Unhandled target architecture.");
149d40ef999SVince Harron return 0;
150d40ef999SVince Harron }
151d40ef999SVince Harron }
152d40ef999SVince Harron
RegisterContextLinux_x86_64(const ArchSpec & target_arch)153b9c1b51eSKate Stone RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(
154b9c1b51eSKate Stone const ArchSpec &target_arch)
155b9c1b51eSKate Stone : lldb_private::RegisterInfoInterface(target_arch),
156af245d11STodd Fiala m_register_info_p(GetRegisterInfoPtr(target_arch)),
157d40ef999SVince Harron m_register_info_count(GetRegisterInfoCount(target_arch)),
158b9c1b51eSKate Stone m_user_register_count(GetUserRegisterInfoCount(target_arch)) {
159*202af507SPavel Labath RegisterInfo orig_ax = {
160*202af507SPavel Labath "orig_rax",
161248a1305SKonrad Kleine nullptr,
162248a1305SKonrad Kleine sizeof(((GPR *)nullptr)->orig_rax),
163b9c1b51eSKate Stone (LLVM_EXTENSION offsetof(GPR, orig_rax)),
164b9c1b51eSKate Stone eEncodingUint,
165b9c1b51eSKate Stone eFormatHex,
166*202af507SPavel Labath {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
167*202af507SPavel Labath LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
168b9c1b51eSKate Stone nullptr,
169b9c1b51eSKate Stone nullptr,
170*202af507SPavel Labath };
1714778e410SRavitheja Addepally d_register_infos.push_back(orig_ax);
1723e699d41SVirgile Bello }
1733e699d41SVirgile Bello
GetGPRSize() const174b9c1b51eSKate Stone size_t RegisterContextLinux_x86_64::GetGPRSize() const { return sizeof(GPR); }
1753e699d41SVirgile Bello
1764778e410SRavitheja Addepally const std::vector<lldb_private::RegisterInfo> *
GetDynamicRegisterInfoP() const177b9c1b51eSKate Stone RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const {
1784778e410SRavitheja Addepally return &d_register_infos;
1794778e410SRavitheja Addepally }
1804778e410SRavitheja Addepally
GetRegisterInfo() const181b9c1b51eSKate Stone const RegisterInfo *RegisterContextLinux_x86_64::GetRegisterInfo() const {
182af245d11STodd Fiala return m_register_info_p;
1833e699d41SVirgile Bello }
1843e699d41SVirgile Bello
GetRegisterCount() const185b9c1b51eSKate Stone uint32_t RegisterContextLinux_x86_64::GetRegisterCount() const {
186af245d11STodd Fiala return m_register_info_count;
187af245d11STodd Fiala }
188d40ef999SVince Harron
GetUserRegisterCount() const189b9c1b51eSKate Stone uint32_t RegisterContextLinux_x86_64::GetUserRegisterCount() const {
190d40ef999SVince Harron return m_user_register_count;
191d40ef999SVince Harron }
192