1 //===-- RegisterContextFreeBSDTests.cpp -----------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // clang-format off
10 #include <sys/types.h>
11 #include <machine/reg.h>
12 // clang-format on
13 
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16 
17 #include "Plugins/Process/Utility/lldb-x86-register-enums.h"
18 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
19 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
GetRegParams(RegisterInfoInterface & ctx,uint32_t reg)24 std::pair<size_t, size_t> GetRegParams(RegisterInfoInterface &ctx,
25                                        uint32_t reg) {
26   const RegisterInfo &info = ctx.GetRegisterInfo()[reg];
27   return {info.byte_offset, info.byte_size};
28 }
29 
30 #define EXPECT_OFF(regname, offset, size)                                      \
31   EXPECT_THAT(GetRegParams(reg_ctx, lldb_##regname),                           \
32               ::testing::Pair(offset + base_offset, size))
33 
34 #if defined(__x86_64__)
35 
36 #define EXPECT_GPR_X86_64(regname)                                             \
37   EXPECT_THAT(                                                                 \
38       GetRegParams(reg_ctx, lldb_##regname##_x86_64),                          \
39       ::testing::Pair(offsetof(reg, r_##regname), sizeof(reg::r_##regname)))
40 #define EXPECT_DBR_X86_64(num)                                                 \
41   EXPECT_OFF(dr##num##_x86_64, offsetof(dbreg, dr[num]), sizeof(dbreg::dr[num]))
42 
TEST(RegisterContextFreeBSDTest,x86_64)43 TEST(RegisterContextFreeBSDTest, x86_64) {
44   ArchSpec arch{"x86_64-unknown-freebsd"};
45   RegisterContextFreeBSD_x86_64 reg_ctx{arch};
46 
47   EXPECT_GPR_X86_64(r15);
48   EXPECT_GPR_X86_64(r14);
49   EXPECT_GPR_X86_64(r13);
50   EXPECT_GPR_X86_64(r12);
51   EXPECT_GPR_X86_64(r11);
52   EXPECT_GPR_X86_64(r10);
53   EXPECT_GPR_X86_64(r9);
54   EXPECT_GPR_X86_64(r8);
55   EXPECT_GPR_X86_64(rdi);
56   EXPECT_GPR_X86_64(rsi);
57   EXPECT_GPR_X86_64(rbp);
58   EXPECT_GPR_X86_64(rbx);
59   EXPECT_GPR_X86_64(rdx);
60   EXPECT_GPR_X86_64(rcx);
61   EXPECT_GPR_X86_64(rax);
62   EXPECT_GPR_X86_64(fs);
63   EXPECT_GPR_X86_64(gs);
64   EXPECT_GPR_X86_64(es);
65   EXPECT_GPR_X86_64(ds);
66   EXPECT_GPR_X86_64(rip);
67   EXPECT_GPR_X86_64(cs);
68   EXPECT_GPR_X86_64(rflags);
69   EXPECT_GPR_X86_64(rsp);
70   EXPECT_GPR_X86_64(ss);
71 
72   // fctrl is the first FPR field, it is used to determine offset of the whole
73   // FPR struct
74   size_t base_offset = reg_ctx.GetRegisterInfo()[lldb_fctrl_x86_64].byte_offset;
75 
76   // assert against FXSAVE struct
77   EXPECT_OFF(fctrl_x86_64, 0x00, 2);
78   EXPECT_OFF(fstat_x86_64, 0x02, 2);
79   // TODO: This is a known bug, abridged ftag should is 8 bits in length.
80   EXPECT_OFF(ftag_x86_64, 0x04, 2);
81   EXPECT_OFF(fop_x86_64, 0x06, 2);
82   // NB: Technically fiseg/foseg are 16-bit long and the higher 16 bits
83   // are reserved.  However, LLDB defines them to be 32-bit long for backwards
84   // compatibility, as they were used to reconstruct FIP/FDP before explicit
85   // register entries for them were added.  Also, this is still how GDB does it.
86   EXPECT_OFF(fioff_x86_64, 0x08, 4);
87   EXPECT_OFF(fiseg_x86_64, 0x0C, 4);
88   EXPECT_OFF(fip_x86_64, 0x08, 8);
89   EXPECT_OFF(fooff_x86_64, 0x10, 4);
90   EXPECT_OFF(foseg_x86_64, 0x14, 4);
91   EXPECT_OFF(fdp_x86_64, 0x10, 8);
92   EXPECT_OFF(mxcsr_x86_64, 0x18, 4);
93   EXPECT_OFF(mxcsrmask_x86_64, 0x1C, 4);
94   EXPECT_OFF(st0_x86_64, 0x20, 10);
95   EXPECT_OFF(st1_x86_64, 0x30, 10);
96   EXPECT_OFF(st2_x86_64, 0x40, 10);
97   EXPECT_OFF(st3_x86_64, 0x50, 10);
98   EXPECT_OFF(st4_x86_64, 0x60, 10);
99   EXPECT_OFF(st5_x86_64, 0x70, 10);
100   EXPECT_OFF(st6_x86_64, 0x80, 10);
101   EXPECT_OFF(st7_x86_64, 0x90, 10);
102   EXPECT_OFF(mm0_x86_64, 0x20, 8);
103   EXPECT_OFF(mm1_x86_64, 0x30, 8);
104   EXPECT_OFF(mm2_x86_64, 0x40, 8);
105   EXPECT_OFF(mm3_x86_64, 0x50, 8);
106   EXPECT_OFF(mm4_x86_64, 0x60, 8);
107   EXPECT_OFF(mm5_x86_64, 0x70, 8);
108   EXPECT_OFF(mm6_x86_64, 0x80, 8);
109   EXPECT_OFF(mm7_x86_64, 0x90, 8);
110   EXPECT_OFF(xmm0_x86_64, 0xA0, 16);
111   EXPECT_OFF(xmm1_x86_64, 0xB0, 16);
112   EXPECT_OFF(xmm2_x86_64, 0xC0, 16);
113   EXPECT_OFF(xmm3_x86_64, 0xD0, 16);
114   EXPECT_OFF(xmm4_x86_64, 0xE0, 16);
115   EXPECT_OFF(xmm5_x86_64, 0xF0, 16);
116   EXPECT_OFF(xmm6_x86_64, 0x100, 16);
117   EXPECT_OFF(xmm7_x86_64, 0x110, 16);
118   EXPECT_OFF(xmm8_x86_64, 0x120, 16);
119   EXPECT_OFF(xmm9_x86_64, 0x130, 16);
120   EXPECT_OFF(xmm10_x86_64, 0x140, 16);
121   EXPECT_OFF(xmm11_x86_64, 0x150, 16);
122   EXPECT_OFF(xmm12_x86_64, 0x160, 16);
123   EXPECT_OFF(xmm13_x86_64, 0x170, 16);
124   EXPECT_OFF(xmm14_x86_64, 0x180, 16);
125   EXPECT_OFF(xmm15_x86_64, 0x190, 16);
126 
127   base_offset = reg_ctx.GetRegisterInfo()[lldb_dr0_x86_64].byte_offset;
128   EXPECT_DBR_X86_64(0);
129   EXPECT_DBR_X86_64(1);
130   EXPECT_DBR_X86_64(2);
131   EXPECT_DBR_X86_64(3);
132   EXPECT_DBR_X86_64(4);
133   EXPECT_DBR_X86_64(5);
134   EXPECT_DBR_X86_64(6);
135   EXPECT_DBR_X86_64(7);
136 }
137 
138 #endif // defined(__x86_64__)
139 
140 #if defined(__i386__) || defined(__x86_64__)
141 
142 #define EXPECT_GPR_I386(regname)                                               \
143   EXPECT_THAT(GetRegParams(reg_ctx, lldb_##regname##_i386),                    \
144               ::testing::Pair(offsetof(native_i386_regs, r_##regname),         \
145                               sizeof(native_i386_regs::r_##regname)))
146 #define EXPECT_DBR_I386(num)                                                   \
147   EXPECT_OFF(dr##num##_i386, offsetof(native_i386_dbregs, dr[num]),            \
148              sizeof(native_i386_dbregs::dr[num]))
149 
TEST(RegisterContextFreeBSDTest,i386)150 TEST(RegisterContextFreeBSDTest, i386) {
151   ArchSpec arch{"i686-unknown-freebsd"};
152   RegisterContextFreeBSD_i386 reg_ctx{arch};
153 
154 #if defined(__i386__)
155   using native_i386_regs = ::reg;
156   using native_i386_dbregs = ::dbreg;
157 #else
158   using native_i386_regs = ::reg32;
159   using native_i386_dbregs = ::dbreg32;
160 #endif
161 
162   EXPECT_GPR_I386(fs);
163   EXPECT_GPR_I386(es);
164   EXPECT_GPR_I386(ds);
165   EXPECT_GPR_I386(edi);
166   EXPECT_GPR_I386(esi);
167   EXPECT_GPR_I386(ebp);
168   EXPECT_GPR_I386(ebx);
169   EXPECT_GPR_I386(edx);
170   EXPECT_GPR_I386(ecx);
171   EXPECT_GPR_I386(eax);
172   EXPECT_GPR_I386(eip);
173   EXPECT_GPR_I386(cs);
174   EXPECT_GPR_I386(eflags);
175   EXPECT_GPR_I386(esp);
176   EXPECT_GPR_I386(ss);
177   EXPECT_GPR_I386(gs);
178 
179   // fctrl is the first FPR field, it is used to determine offset of the whole
180   // FPR struct
181   size_t base_offset = reg_ctx.GetRegisterInfo()[lldb_fctrl_i386].byte_offset;
182 
183   // assert against FXSAVE struct
184   EXPECT_OFF(fctrl_i386, 0x00, 2);
185   EXPECT_OFF(fstat_i386, 0x02, 2);
186   // TODO: This is a known bug, abridged ftag should is 8 bits in length.
187   EXPECT_OFF(ftag_i386, 0x04, 2);
188   EXPECT_OFF(fop_i386, 0x06, 2);
189   // NB: Technically fiseg/foseg are 16-bit long and the higher 16 bits
190   // are reserved.  However, we use them to access/recombine 64-bit FIP/FDP.
191   EXPECT_OFF(fioff_i386, 0x08, 4);
192   EXPECT_OFF(fiseg_i386, 0x0C, 4);
193   EXPECT_OFF(fooff_i386, 0x10, 4);
194   EXPECT_OFF(foseg_i386, 0x14, 4);
195   EXPECT_OFF(mxcsr_i386, 0x18, 4);
196   EXPECT_OFF(mxcsrmask_i386, 0x1C, 4);
197   EXPECT_OFF(st0_i386, 0x20, 10);
198   EXPECT_OFF(st1_i386, 0x30, 10);
199   EXPECT_OFF(st2_i386, 0x40, 10);
200   EXPECT_OFF(st3_i386, 0x50, 10);
201   EXPECT_OFF(st4_i386, 0x60, 10);
202   EXPECT_OFF(st5_i386, 0x70, 10);
203   EXPECT_OFF(st6_i386, 0x80, 10);
204   EXPECT_OFF(st7_i386, 0x90, 10);
205   EXPECT_OFF(mm0_i386, 0x20, 8);
206   EXPECT_OFF(mm1_i386, 0x30, 8);
207   EXPECT_OFF(mm2_i386, 0x40, 8);
208   EXPECT_OFF(mm3_i386, 0x50, 8);
209   EXPECT_OFF(mm4_i386, 0x60, 8);
210   EXPECT_OFF(mm5_i386, 0x70, 8);
211   EXPECT_OFF(mm6_i386, 0x80, 8);
212   EXPECT_OFF(mm7_i386, 0x90, 8);
213   EXPECT_OFF(xmm0_i386, 0xA0, 16);
214   EXPECT_OFF(xmm1_i386, 0xB0, 16);
215   EXPECT_OFF(xmm2_i386, 0xC0, 16);
216   EXPECT_OFF(xmm3_i386, 0xD0, 16);
217   EXPECT_OFF(xmm4_i386, 0xE0, 16);
218   EXPECT_OFF(xmm5_i386, 0xF0, 16);
219   EXPECT_OFF(xmm6_i386, 0x100, 16);
220   EXPECT_OFF(xmm7_i386, 0x110, 16);
221 
222   base_offset = reg_ctx.GetRegisterInfo()[lldb_dr0_i386].byte_offset;
223   EXPECT_DBR_I386(0);
224   EXPECT_DBR_I386(1);
225   EXPECT_DBR_I386(2);
226   EXPECT_DBR_I386(3);
227   EXPECT_DBR_I386(4);
228   EXPECT_DBR_I386(5);
229   EXPECT_DBR_I386(6);
230   EXPECT_DBR_I386(7);
231 }
232 
233 #endif // defined(__i386__) || defined(__x86_64__)
234