1 //===-- RegisterContextLinux_x86_64.h --------------------------*- 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 "llvm/Support/Compiler.h"
11 #include "RegisterContextLinux_x86_64.h"
12 #include <vector>
13
14 using namespace lldb_private;
15
16 // Computes the offset of the given GPR in the user data area.
17 #define GPR_OFFSET(regname) \
18 (offsetof(GPR, regname))
19
20 // Update the Linux specific information (offset and size).
21 #define UPDATE_GPR_INFO(reg) \
22 do { \
23 GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
24 GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
25 } while(false);
26
27 #define UPDATE_I386_GPR_INFO(i386_reg, reg) \
28 do { \
29 GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
30 } while(false);
31
32 #define DR_OFFSET(reg_index) \
33 (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
34
35 #define UPDATE_DR_INFO(reg_index) \
36 do { \
37 GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
38 GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
39 } while(false);
40
41 typedef struct _GPR
42 {
43 uint64_t r15;
44 uint64_t r14;
45 uint64_t r13;
46 uint64_t r12;
47 uint64_t rbp;
48 uint64_t rbx;
49 uint64_t r11;
50 uint64_t r10;
51 uint64_t r9;
52 uint64_t r8;
53 uint64_t rax;
54 uint64_t rcx;
55 uint64_t rdx;
56 uint64_t rsi;
57 uint64_t rdi;
58 uint64_t orig_ax;
59 uint64_t rip;
60 uint64_t cs;
61 uint64_t rflags;
62 uint64_t rsp;
63 uint64_t ss;
64 uint64_t fs_base;
65 uint64_t gs_base;
66 uint64_t ds;
67 uint64_t es;
68 uint64_t fs;
69 uint64_t gs;
70 } GPR;
71
72 typedef RegisterContext_x86_64::FXSAVE FXSAVE;
73
74 struct UserArea
75 {
76 GPR gpr; // General purpose registers.
77 int32_t fpvalid; // True if FPU is being used.
78 int32_t pad0;
79 FXSAVE i387; // General purpose floating point registers (see FPR for extended register sets).
80 uint64_t tsize; // Text segment size.
81 uint64_t dsize; // Data segment size.
82 uint64_t ssize; // Stack segment size.
83 uint64_t start_code; // VM address of text.
84 uint64_t start_stack; // VM address of stack bottom (top in rsp).
85 int64_t signal; // Signal causing core dump.
86 int32_t reserved; // Unused.
87 int32_t pad1;
88 uint64_t ar0; // Location of GPR's.
89 FXSAVE* fpstate; // Location of FPR's.
90 uint64_t magic; // Identifier for core dumps.
91 char u_comm[32]; // Command causing core dump.
92 uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).
93 uint64_t error_code; // CPU error code.
94 uint64_t fault_address; // Control register CR3.
95 };
96
97 // Use a singleton function to avoid global constructors in shared libraries.
GetRegisterContext()98 static std::vector<RegisterInfo> & GetRegisterContext () {
99 static std::vector<RegisterInfo> g_register_infos;
100 return g_register_infos;
101 }
102
RegisterContextLinux_x86_64(Thread & thread,uint32_t concrete_frame_idx)103 RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
104 RegisterContext_x86_64(thread, concrete_frame_idx)
105 {
106 }
107
108 size_t
GetGPRSize()109 RegisterContextLinux_x86_64::GetGPRSize()
110 {
111 return sizeof(GPR);
112 }
113
114 const RegisterInfo *
GetRegisterInfo()115 RegisterContextLinux_x86_64::GetRegisterInfo()
116 {
117 // Allocate RegisterInfo only once
118 if (GetRegisterContext().empty())
119 {
120 // Copy the register information from base class
121 const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
122 if (base_info)
123 {
124 GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
125 // Update the Linux specific register information (offset and size).
126 UpdateRegisterInfo();
127 }
128 }
129 return &GetRegisterContext()[0];
130 }
131
132 void
UpdateRegisterInfo()133 RegisterContextLinux_x86_64::UpdateRegisterInfo()
134 {
135 UPDATE_GPR_INFO(rax);
136 UPDATE_GPR_INFO(rbx);
137 UPDATE_GPR_INFO(rcx);
138 UPDATE_GPR_INFO(rdx);
139 UPDATE_GPR_INFO(rdi);
140 UPDATE_GPR_INFO(rsi);
141 UPDATE_GPR_INFO(rbp);
142 UPDATE_GPR_INFO(rsp);
143 UPDATE_GPR_INFO(r8);
144 UPDATE_GPR_INFO(r9);
145 UPDATE_GPR_INFO(r10);
146 UPDATE_GPR_INFO(r11);
147 UPDATE_GPR_INFO(r12);
148 UPDATE_GPR_INFO(r13);
149 UPDATE_GPR_INFO(r14);
150 UPDATE_GPR_INFO(r15);
151 UPDATE_GPR_INFO(rip);
152 UPDATE_GPR_INFO(rflags);
153 UPDATE_GPR_INFO(cs);
154 UPDATE_GPR_INFO(fs);
155 UPDATE_GPR_INFO(gs);
156 UPDATE_GPR_INFO(ss);
157 UPDATE_GPR_INFO(ds);
158 UPDATE_GPR_INFO(es);
159
160 UPDATE_I386_GPR_INFO(eax, rax);
161 UPDATE_I386_GPR_INFO(ebx, rbx);
162 UPDATE_I386_GPR_INFO(ecx, rcx);
163 UPDATE_I386_GPR_INFO(edx, rdx);
164 UPDATE_I386_GPR_INFO(edi, rdi);
165 UPDATE_I386_GPR_INFO(esi, rsi);
166 UPDATE_I386_GPR_INFO(ebp, rbp);
167 UPDATE_I386_GPR_INFO(esp, rsp);
168 UPDATE_I386_GPR_INFO(eip, rip);
169 UPDATE_I386_GPR_INFO(eflags, rflags);
170
171 UPDATE_DR_INFO(0);
172 UPDATE_DR_INFO(1);
173 UPDATE_DR_INFO(2);
174 UPDATE_DR_INFO(3);
175 UPDATE_DR_INFO(4);
176 UPDATE_DR_INFO(5);
177 UPDATE_DR_INFO(6);
178 UPDATE_DR_INFO(7);
179 }
180
181