1 //===-- RegisterContextLinux_x86_64.cpp ------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===---------------------------------------------------------------------===//
9 
10 #include <vector>
11 #include "RegisterContextPOSIX_x86.h"
12 #include "RegisterContextLinux_i386.h"
13 #include "RegisterContextLinux_x86_64.h"
14 
15 using namespace lldb_private;
16 using namespace lldb;
17 
18 typedef struct _GPR
19 {
20     uint64_t r15;
21     uint64_t r14;
22     uint64_t r13;
23     uint64_t r12;
24     uint64_t rbp;
25     uint64_t rbx;
26     uint64_t r11;
27     uint64_t r10;
28     uint64_t r9;
29     uint64_t r8;
30     uint64_t rax;
31     uint64_t rcx;
32     uint64_t rdx;
33     uint64_t rsi;
34     uint64_t rdi;
35     uint64_t orig_rax;
36     uint64_t rip;
37     uint64_t cs;
38     uint64_t rflags;
39     uint64_t rsp;
40     uint64_t ss;
41     uint64_t fs_base;
42     uint64_t gs_base;
43     uint64_t ds;
44     uint64_t es;
45     uint64_t fs;
46     uint64_t gs;
47 } GPR;
48 
49 struct DBG {
50     uint64_t dr[8];
51 };
52 
53 struct UserArea
54 {
55     GPR      gpr;           // General purpose registers.
56     int32_t  fpvalid;       // True if FPU is being used.
57     int32_t  pad0;
58     FXSAVE   fpr;           // General purpose floating point registers (see FPR for extended register sets).
59     uint64_t tsize;         // Text segment size.
60     uint64_t dsize;         // Data segment size.
61     uint64_t ssize;         // Stack segment size.
62     uint64_t start_code;    // VM address of text.
63     uint64_t start_stack;   // VM address of stack bottom (top in rsp).
64     int64_t  signal;        // Signal causing core dump.
65     int32_t  reserved;      // Unused.
66     int32_t  pad1;
67     uint64_t ar0;           // Location of GPR's.
68     FXSAVE*  fpstate;       // Location of FPR's.
69     uint64_t magic;         // Identifier for core dumps.
70     char     u_comm[32];    // Command causing core dump.
71     DBG      dbg;           // Debug registers.
72     uint64_t error_code;    // CPU error code.
73     uint64_t fault_address; // Control register CR3.
74 };
75 
76 
77 #define DR_OFFSET(reg_index) \
78     (LLVM_EXTENSION offsetof(UserArea, dbg) + \
79      LLVM_EXTENSION offsetof(DBG, dr[reg_index]))
80 
81 //---------------------------------------------------------------------------
82 // Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
83 //---------------------------------------------------------------------------
84 #define DECLARE_REGISTER_INFOS_X86_64_STRUCT
85 #include "RegisterInfos_x86_64.h"
86 #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
87 
88 static std::vector<lldb_private::RegisterInfo>&
89 GetPrivateRegisterInfoVector ()
90 {
91     static std::vector<lldb_private::RegisterInfo> g_register_infos;
92     return g_register_infos;
93 }
94 
95 static const RegisterInfo *
96 GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
97 {
98     std::vector<lldb_private::RegisterInfo> &g_register_infos = GetPrivateRegisterInfoVector ();
99 
100     // Allocate RegisterInfo only once
101     if (g_register_infos.empty())
102     {
103         // Copy the register information from base class
104         std::unique_ptr<RegisterContextLinux_i386> reg_interface(new RegisterContextLinux_i386 (arch));
105         const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
106         g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]);
107 
108         //---------------------------------------------------------------------------
109         // Include RegisterInfos_x86_64 to update the g_register_infos structure
110         //  with x86_64 offsets.
111         //---------------------------------------------------------------------------
112         #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
113         #include "RegisterInfos_x86_64.h"
114         #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
115     }
116 
117     return &g_register_infos[0];
118 }
119 
120 static const RegisterInfo *
121 GetRegisterInfoPtr (const ArchSpec &target_arch)
122 {
123     switch (target_arch.GetMachine())
124     {
125         case llvm::Triple::x86:
126             return GetRegisterInfo_i386 (target_arch);
127         case llvm::Triple::x86_64:
128             return g_register_infos_x86_64;
129         default:
130             assert(false && "Unhandled target architecture.");
131             return nullptr;
132     }
133 }
134 
135 static uint32_t
136 GetRegisterInfoCount (const ArchSpec &target_arch)
137 {
138     switch (target_arch.GetMachine())
139     {
140         case llvm::Triple::x86:
141             {
142                 assert (!GetPrivateRegisterInfoVector ().empty () && "i386 register info not yet filled.");
143                 return static_cast<uint32_t> (GetPrivateRegisterInfoVector ().size ());
144             }
145         case llvm::Triple::x86_64:
146             return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0]));
147         default:
148             assert(false && "Unhandled target architecture.");
149             return 0;
150     }
151 }
152 
153 static uint32_t
154 GetUserRegisterInfoCount (const ArchSpec &target_arch)
155 {
156     switch (target_arch.GetMachine())
157     {
158         case llvm::Triple::x86:
159             return static_cast<uint32_t> (k_num_user_registers_i386);
160         case llvm::Triple::x86_64:
161             return static_cast<uint32_t> (k_num_user_registers_x86_64);
162         default:
163             assert(false && "Unhandled target architecture.");
164             return 0;
165     }
166 }
167 
168 RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
169     lldb_private::RegisterInfoInterface(target_arch),
170     m_register_info_p (GetRegisterInfoPtr (target_arch)),
171     m_register_info_count (GetRegisterInfoCount (target_arch)),
172     m_user_register_count (GetUserRegisterInfoCount (target_arch))
173 {
174     RegisterInfo orig_ax = { "orig_rax", NULL, sizeof(((GPR*)NULL)->orig_rax), (LLVM_EXTENSION offsetof(GPR, orig_rax)), eEncodingUint, \
175               eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL };
176     d_register_infos.push_back(orig_ax);
177 }
178 
179 size_t
180 RegisterContextLinux_x86_64::GetGPRSize() const
181 {
182     return sizeof(GPR);
183 }
184 
185 const std::vector<lldb_private::RegisterInfo> *
186 RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const
187 {
188     return &d_register_infos;
189 }
190 
191 const RegisterInfo *
192 RegisterContextLinux_x86_64::GetRegisterInfo() const
193 {
194     return m_register_info_p;
195 }
196 
197 uint32_t
198 RegisterContextLinux_x86_64::GetRegisterCount () const
199 {
200     return m_register_info_count;
201 }
202 
203 uint32_t
204 RegisterContextLinux_x86_64::GetUserRegisterCount () const
205 {
206     return m_user_register_count;
207 }
208