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