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 }