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
14using 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)                                                \
22do {                                                                        \
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)                                 \
28do {                                                                        \
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)                                                \
36do {                                                                             \
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
41typedef 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
72typedef RegisterContext_x86_64::FXSAVE FXSAVE;
73
74struct 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.
98static std::vector<RegisterInfo> & GetRegisterContext () {
99    static std::vector<RegisterInfo> g_register_infos;
100    return g_register_infos;
101}
102
103RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
104    RegisterContext_x86_64(thread, concrete_frame_idx)
105{
106}
107
108size_t
109RegisterContextLinux_x86_64::GetGPRSize()
110{
111    return sizeof(GPR);
112}
113
114const RegisterInfo *
115RegisterContextLinux_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
132void
133RegisterContextLinux_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