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_ax;
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 // Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
78 //---------------------------------------------------------------------------
79 #define DECLARE_REGISTER_INFOS_X86_64_STRUCT
80 #include "RegisterInfos_x86_64.h"
81 #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
82 
83 static std::vector<lldb_private::RegisterInfo>&
84 GetPrivateRegisterInfoVector ()
85 {
86     static std::vector<lldb_private::RegisterInfo> g_register_infos;
87     return g_register_infos;
88 }
89 
90 static const RegisterInfo *
91 GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
92 {
93     std::vector<lldb_private::RegisterInfo> &g_register_infos = GetPrivateRegisterInfoVector ();
94 
95     // Allocate RegisterInfo only once
96     if (g_register_infos.empty())
97     {
98         // Copy the register information from base class
99         std::unique_ptr<RegisterContextLinux_i386> reg_interface(new RegisterContextLinux_i386 (arch));
100         const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
101         g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]);
102 
103         //---------------------------------------------------------------------------
104         // Include RegisterInfos_x86_64 to update the g_register_infos structure
105         //  with x86_64 offsets.
106         //---------------------------------------------------------------------------
107         #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
108         #include "RegisterInfos_x86_64.h"
109         #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
110     }
111 
112     return &g_register_infos[0];
113 }
114 
115 static const RegisterInfo *
116 GetRegisterInfoPtr (const ArchSpec &target_arch)
117 {
118     switch (target_arch.GetMachine())
119     {
120         case llvm::Triple::x86:
121             return GetRegisterInfo_i386 (target_arch);
122         case llvm::Triple::x86_64:
123             return g_register_infos_x86_64;
124         default:
125             assert(false && "Unhandled target architecture.");
126             return nullptr;
127     }
128 }
129 
130 static uint32_t
131 GetRegisterInfoCount (const ArchSpec &target_arch)
132 {
133     switch (target_arch.GetMachine())
134     {
135         case llvm::Triple::x86:
136             {
137                 assert (!GetPrivateRegisterInfoVector ().empty () && "i386 register info not yet filled.");
138                 return static_cast<uint32_t> (GetPrivateRegisterInfoVector ().size ());
139             }
140         case llvm::Triple::x86_64:
141             return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0]));
142         default:
143             assert(false && "Unhandled target architecture.");
144             return 0;
145     }
146 }
147 
148 static uint32_t
149 GetUserRegisterInfoCount (const ArchSpec &target_arch)
150 {
151     switch (target_arch.GetMachine())
152     {
153         case llvm::Triple::x86:
154             return static_cast<uint32_t> (k_num_user_registers_i386);
155         case llvm::Triple::x86_64:
156             return static_cast<uint32_t> (k_num_user_registers_x86_64);
157         default:
158             assert(false && "Unhandled target architecture.");
159             return 0;
160     }
161 }
162 
163 RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
164     lldb_private::RegisterInfoInterface(target_arch),
165     m_register_info_p (GetRegisterInfoPtr (target_arch)),
166     m_register_info_count (GetRegisterInfoCount (target_arch)),
167     m_user_register_count (GetUserRegisterInfoCount (target_arch))
168 {
169 }
170 
171 size_t
172 RegisterContextLinux_x86_64::GetGPRSize() const
173 {
174     return sizeof(GPR);
175 }
176 
177 const RegisterInfo *
178 RegisterContextLinux_x86_64::GetRegisterInfo() const
179 {
180     return m_register_info_p;
181 }
182 
183 uint32_t
184 RegisterContextLinux_x86_64::GetRegisterCount () const
185 {
186     return m_register_info_count;
187 }
188 
189 uint32_t
190 RegisterContextLinux_x86_64::GetUserRegisterCount () const
191 {
192     return m_user_register_count;
193 }
194