1 // Copyright 2012 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // asm/sigcontext.h can't be included with signal.h on glibc or
30 // musl, so only compare _libc_fpstate and _fpstate on Android.
31 #if defined(__ANDROID__) && defined(__x86_64__)
32 #ifdef HAVE_CONFIG_H
33 #include <config.h> // Must come first
34 #endif
35
36 #include <asm/sigcontext.h>
37 #endif
38
39 #include <sys/ucontext.h>
40
41 #include <type_traits>
42
43 #include "breakpad_googletest_includes.h"
44 #include "common/linux/ucontext_constants.h"
45
46 template <int left, int right>
47 struct CompileAssertEquals {
48 // a compilation error here indicates left and right are not equal.
49 char left_too_large[right - left];
50 // a compilation error here indicates left and right are not equal.
51 char right_too_large[left - right];
52 };
53
54 #define COMPILE_ASSERT_EQ(left, right, tag) \
55 CompileAssertEquals<left, right> tag;
56
TEST(AndroidUContext,GRegsOffset)57 TEST(AndroidUContext, GRegsOffset) {
58 #if defined(__arm__)
59 // There is no gregs[] array on ARM, so compare to the offset of
60 // first register fields, since they're stored in order.
61 ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
62 offsetof(ucontext_t,uc_mcontext.arm_r0));
63 #elif defined(__aarch64__)
64 // There is no gregs[] array on ARM, so compare to the offset of
65 // first register fields, since they're stored in order.
66 ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
67 offsetof(ucontext_t,uc_mcontext.regs[0]));
68 ASSERT_EQ(static_cast<size_t>(MCONTEXT_SP_OFFSET),
69 offsetof(ucontext_t,uc_mcontext.sp));
70 ASSERT_EQ(static_cast<size_t>(MCONTEXT_PC_OFFSET),
71 offsetof(ucontext_t,uc_mcontext.pc));
72 ASSERT_EQ(static_cast<size_t>(MCONTEXT_PSTATE_OFFSET),
73 offsetof(ucontext_t,uc_mcontext.pstate));
74 ASSERT_EQ(static_cast<size_t>(MCONTEXT_EXTENSION_OFFSET),
75 offsetof(ucontext_t,uc_mcontext.__reserved));
76 #elif defined(__i386__)
77 ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
78 offsetof(ucontext_t,uc_mcontext.gregs));
79 #define CHECK_REG(x) \
80 ASSERT_EQ(static_cast<size_t>(MCONTEXT_##x##_OFFSET), \
81 offsetof(ucontext_t,uc_mcontext.gregs[REG_##x]))
82 CHECK_REG(GS);
83 CHECK_REG(FS);
84 CHECK_REG(ES);
85 CHECK_REG(DS);
86 CHECK_REG(EDI);
87 CHECK_REG(ESI);
88 CHECK_REG(EBP);
89 CHECK_REG(ESP);
90 CHECK_REG(EBX);
91 CHECK_REG(EDX);
92 CHECK_REG(ECX);
93 CHECK_REG(EAX);
94 CHECK_REG(TRAPNO);
95 CHECK_REG(ERR);
96 CHECK_REG(EIP);
97 CHECK_REG(CS);
98 CHECK_REG(EFL);
99 CHECK_REG(UESP);
100 CHECK_REG(SS);
101
102 ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_OFFSET),
103 offsetof(ucontext_t,uc_mcontext.fpregs));
104
105 ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_MEM_OFFSET),
106 offsetof(ucontext_t,__fpregs_mem));
107 #elif defined(__mips__)
108 ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
109 offsetof(ucontext_t,uc_mcontext.gregs));
110
111 // PC for mips is not part of gregs.
112 ASSERT_EQ(static_cast<size_t>(MCONTEXT_PC_OFFSET),
113 offsetof(ucontext_t,uc_mcontext.pc));
114
115 ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPREGS_OFFSET),
116 offsetof(ucontext_t,uc_mcontext.fpregs));
117
118 ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPC_CSR),
119 offsetof(ucontext_t,uc_mcontext.fpc_csr));
120 #elif defined(__riscv)
121 ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
122 offsetof(ucontext_t,uc_mcontext.__gregs[0]));
123
124 #define CHECK_REG(x) \
125 ASSERT_EQ(static_cast<size_t>(MCONTEXT_##x##_OFFSET), \
126 offsetof(ucontext_t,uc_mcontext.__gregs[REG_##x]))
127 CHECK_REG(PC)
128 CHECK_REG(RA)
129 CHECK_REG(SP)
130 CHECK_REG(S0)
131 CHECK_REG(S1)
132 CHECK_REG(S2)
133
134 ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPREGS_OFFSET),
135 offsetof(ucontext_t,uc_mcontext.__fpregs));
136
137 ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPC_CSR),
138 offsetof(ucontext_t,uc_mcontext.__fpregs.__fcsr));
139 #elif defined(__x86_64__)
140
141 COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
142 offsetof(ucontext_t,uc_mcontext.gregs),
143 mcontext_gregs_offset);
144 #define CHECK_REG(x) \
145 COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_##x), \
146 offsetof(ucontext_t,uc_mcontext.gregs[REG_##x]), reg_##x)
147 CHECK_REG(R8);
148 CHECK_REG(R9);
149 CHECK_REG(R10);
150 CHECK_REG(R11);
151 CHECK_REG(R12);
152 CHECK_REG(R13);
153 CHECK_REG(R14);
154 CHECK_REG(R15);
155 CHECK_REG(RDI);
156 CHECK_REG(RSI);
157 CHECK_REG(RBP);
158 CHECK_REG(RBX);
159 CHECK_REG(RDX);
160 CHECK_REG(RAX);
161 CHECK_REG(RCX);
162 CHECK_REG(RSP);
163 CHECK_REG(RIP);
164
165 // sigcontext is an analog to mcontext_t. The layout should be the same.
166 COMPILE_ASSERT_EQ(offsetof(mcontext_t,fpregs),
167 offsetof(sigcontext,fpstate), sigcontext_fpstate);
168
169 #if defined(__ANDROID__)
170 // Check that _fpstate from asm/sigcontext.h is essentially the same
171 // as _libc_fpstate.
172 COMPILE_ASSERT_EQ(sizeof(_libc_fpstate), sizeof(_fpstate),
173 sigcontext_fpstate_size);
174 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,cwd),offsetof(_fpstate,cwd),
175 sigcontext_fpstate_cwd);
176 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,swd),offsetof(_fpstate,swd),
177 sigcontext_fpstate_swd);
178 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,ftw),offsetof(_fpstate,twd),
179 sigcontext_fpstate_twd);
180 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,fop),offsetof(_fpstate,fop),
181 sigcontext_fpstate_fop);
182 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,rip),offsetof(_fpstate,rip),
183 sigcontext_fpstate_rip);
184 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,rdp),offsetof(_fpstate,rdp),
185 sigcontext_fpstate_rdp);
186 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,mxcsr),offsetof(_fpstate,mxcsr),
187 sigcontext_fpstate_mxcsr);
188 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,mxcr_mask),
189 offsetof(_fpstate,mxcsr_mask),
190 sigcontext_fpstate_mxcsr_mask);
191 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,_st), offsetof(_fpstate,st_space),
192 sigcontext_fpstate_stspace);
193 COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,_xmm), offsetof(_fpstate,xmm_space),
194 sigcontext_fpstate_xmm_space);
195 #endif
196
197 COMPILE_ASSERT_EQ(MCONTEXT_FPREGS_PTR,
198 offsetof(ucontext_t,uc_mcontext.fpregs),
199 mcontext_fpregs_ptr);
200 COMPILE_ASSERT_EQ(MCONTEXT_FPREGS_MEM, offsetof(ucontext_t,__fpregs_mem),
201 mcontext_fpregs_mem);
202 COMPILE_ASSERT_EQ(FPREGS_OFFSET_MXCSR,
203 offsetof(std::remove_pointer<fpregset_t>::type,mxcsr),
204 fpregs_offset_mxcsr);
205 COMPILE_ASSERT_EQ(UCONTEXT_SIGMASK_OFFSET, offsetof(ucontext_t, uc_sigmask),
206 ucontext_sigmask);
207 #else
208 ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
209 offsetof(ucontext_t,uc_mcontext.gregs));
210 #endif
211 }
212
TEST(AndroidUContext,SigmakOffset)213 TEST(AndroidUContext, SigmakOffset) {
214 ASSERT_EQ(static_cast<size_t>(UCONTEXT_SIGMASK_OFFSET),
215 offsetof(ucontext_t,uc_sigmask));
216 }
217