xref: /aosp_15_r20/external/google-breakpad/src/common/linux/breakpad_getcontext_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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