1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <private/bionic_asm.h>
34
35// The internal structure of a jmp_buf is totally private.
36// Current layout (changes from release to release):
37//
38// word   name            description
39// 0      edx             registers
40// 1      ebx
41// 2      esp
42// 3      ebp
43// 4      esi
44// 5      edi
45// 6      sigmask         64-bit signal mask (not used with _setjmp / _longjmp)
46// 7      "               "
47// 8      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
48// 9      checksum        checksum of the core registers, to give better error messages.
49
50#define _JB_EDX 0
51#define _JB_EBX 1
52#define _JB_ESP 2
53#define _JB_EBP 3
54#define _JB_ESI 4
55#define _JB_EDI 5
56#define _JB_SIGMASK 6
57#define _JB_SIGFLAG 8
58#define _JB_CHECKSUM 9
59
60.macro m_calculate_checksum dst, src
61  movl $0, \dst
62  .irp i,0,1,2,3,4,5
63    xorl (\i*4)(\src), \dst
64  .endr
65.endm
66
67ENTRY(setjmp)
68__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
69  movl 4(%esp),%ecx
70  mov $1,%eax
71  jmp .L_sigsetjmp
72END(setjmp)
73
74ENTRY(_setjmp)
75__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
76  movl 4(%esp),%ecx
77  movl $0,%eax
78  jmp .L_sigsetjmp
79END(_setjmp)
80
81ENTRY(sigsetjmp)
82__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
83  movl 4(%esp),%ecx
84  movl 8(%esp),%eax
85
86.L_sigsetjmp:
87  PIC_PROLOGUE
88  pushl %eax
89  call PIC_PLT(__bionic_setjmp_cookie_get)
90  addl $4,%esp
91  PIC_EPILOGUE
92
93  // Record the setjmp cookie and whether or not we're saving the signal mask.
94  movl %eax,(_JB_SIGFLAG * 4)(%ecx)
95
96  // Do we need to save the signal mask?
97  testl $1,%eax
98  jz 1f
99
100  // Save the current signal mask.
101  pushl %ecx
102  PIC_PROLOGUE
103  leal (_JB_SIGMASK * 4)(%ecx),%eax
104  pushl %eax
105  pushl $0 // NULL
106  pushl $2 // SIG_SETMASK
107  call PIC_PLT(sigprocmask64)
108  addl $12,%esp
109  PIC_EPILOGUE
110  popl %ecx
111
1121:
113  // Fetch the setjmp cookie and clear the signal flag bit.
114  movl (_JB_SIGFLAG * 4)(%ecx),%eax
115  andl $-2,%eax
116
117  // Save the callee-save registers.
118  movl 0(%esp),%edx
119
120.macro m_mangle_register reg, offset
121  movl \reg,(\offset * 4)(%ecx)
122  xorl %eax,(\offset * 4)(%ecx)
123.endm
124  m_mangle_register %edx, _JB_EDX
125  m_mangle_register %ebx, _JB_EBX
126  m_mangle_register %esp, _JB_ESP
127  m_mangle_register %ebp, _JB_EBP
128  m_mangle_register %esi, _JB_ESI
129  m_mangle_register %edi, _JB_EDI
130
131  m_calculate_checksum %eax, %ecx
132  movl %eax, (_JB_CHECKSUM * 4)(%ecx)
133
134  xorl %eax,%eax
135  ret
136END(sigsetjmp)
137
138ENTRY(siglongjmp)
139__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
140  movl 4(%esp),%edx
141
142  // Check the checksum before doing anything.
143  m_calculate_checksum %eax, %edx
144  xorl (_JB_CHECKSUM * 4)(%edx), %eax
145  jnz 3f
146
147  // Do we have a signal mask to restore?
148  movl (_JB_SIGFLAG * 4)(%edx), %eax
149  testl $1,%eax
150  jz 1f
151
152  // Restore the signal mask.
153  leal (_JB_SIGMASK * 4)(%edx),%eax
154  PIC_PROLOGUE
155  pushl $0 // NULL
156  pushl %eax
157  pushl $2 // SIG_SETMASK
158  call PIC_PLT(sigprocmask64)
159  addl $12,%esp
160  PIC_EPILOGUE
161
1621:
163  // Restore the callee-save registers.
164  movl 4(%esp),%edx
165  movl 8(%esp),%eax
166
167  // Fetch the setjmp cookie and clear the signal flag bit.
168  movl (_JB_SIGFLAG * 4)(%edx),%ecx
169  andl $-2,%ecx
170
171  // Carefully unmangle esp/ebp without ever having an invalid value in the
172  // register (http://b/152210274).
173  movl (_JB_ESP * 4)(%edx),%edi
174  xorl %ecx,%edi
175  movl %edi,%esp
176  movl (_JB_EBP * 4)(%edx),%edi
177  xorl %ecx,%edi
178  movl %edi,%ebp
179
180  // The others don't matter as much, but we do need to finish using the cookie
181  // from %ecx before we clobber it, so we seed each register with the cookie.
182  movl %ecx,%ebx
183  movl %ecx,%esi
184  movl %ecx,%edi
185  xorl (_JB_EDX * 4)(%edx),%ecx
186  xorl (_JB_EBX * 4)(%edx),%ebx
187  xorl (_JB_ESI * 4)(%edx),%esi
188  xorl (_JB_EDI * 4)(%edx),%edi
189
190  PIC_PROLOGUE
191  pushl %eax
192  pushl %ecx
193  pushl (_JB_SIGFLAG * 4)(%edx)
194  call PIC_PLT(__bionic_setjmp_cookie_check)
195  addl $4,%esp
196  popl %ecx
197  popl %eax
198  PIC_EPILOGUE
199
200  testl %eax,%eax
201  jnz 2f
202  incl %eax
2032:
204  movl %ecx,0(%esp)
205  ret
206
2073:
208  PIC_PROLOGUE
209  pushl (_JB_SIGMASK * 4)(%edx)
210  call PIC_PLT(__bionic_setjmp_checksum_mismatch)
211END(siglongjmp)
212
213ALIAS_SYMBOL(longjmp, siglongjmp)
214__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
215ALIAS_SYMBOL(_longjmp, siglongjmp)
216__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
217