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