/ src / common / linux / breakpad_getcontext_unittest.cc
breakpad_getcontext_unittest.cc
  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  
 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  
213  TEST(AndroidUContext, SigmakOffset) {
214    ASSERT_EQ(static_cast<size_t>(UCONTEXT_SIGMASK_OFFSET),
215              offsetof(ucontext_t,uc_sigmask));
216  }