1/*
2 * Copyright (c) 2001 Wasabi Systems, Inc.
3 * All rights reserved.
4 *
5 * Written by Frank van der Linden for Wasabi Systems, Inc.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed for the NetBSD Project by
18 *      Wasabi Systems, Inc.
19 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
20 *    or promote products derived from this software without specific prior
21 *    written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <private/bionic_asm.h>
37
38
39// The internal structure of a jmp_buf is totally private.
40// Current layout (changes from release to release):
41//
42// word   name            description
43// 0      rbx             registers
44// 1      rbp
45// 2      r12
46// 3      r13
47// 4      r14
48// 5      r15
49// 6      rsp
50// 7      pc
51// 8      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
52// 9      sigmask         signal mask (includes rt signals as well)
53// 10     checksum        checksum of the core registers, to give better error messages.
54
55#define _JB_RBX 0
56#define _JB_RBP 1
57#define _JB_R12 2
58#define _JB_R13 3
59#define _JB_R14 4
60#define _JB_R15 5
61#define _JB_RSP 6
62#define _JB_PC 7
63#define _JB_SIGFLAG 8
64#define _JB_SIGMASK 9
65#define _JB_CHECKSUM 10
66
67#define MANGLE_REGISTERS 1
68
69.macro m_mangle_registers reg
70#if MANGLE_REGISTERS
71  xorq \reg,%rbx
72  xorq \reg,%rbp
73  xorq \reg,%r12
74  xorq \reg,%r13
75  xorq \reg,%r14
76  xorq \reg,%r15
77  xorq \reg,%rsp
78  xorq \reg,%r11
79#endif
80.endm
81
82.macro m_unmangle_registers reg
83  m_mangle_registers \reg
84.endm
85
86.macro m_calculate_checksum dst, src
87  movq $0, \dst
88  .irp i,0,1,2,3,4,5,6,7
89    xorq (\i*8)(\src), \dst
90  .endr
91.endm
92
93ENTRY(setjmp)
94__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
95  movl $1,%esi
96  jmp PIC_PLT(sigsetjmp)
97END(setjmp)
98
99ENTRY(_setjmp)
100__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
101  movl $0,%esi
102  jmp PIC_PLT(sigsetjmp)
103END(_setjmp)
104
105// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
106ENTRY(sigsetjmp)
107__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
108  pushq %rdi
109  movq %rsi,%rdi
110  call PIC_PLT(__bionic_setjmp_cookie_get)
111  popq %rdi
112
113  // Record setjmp cookie and whether or not we're saving the signal mask.
114  movq %rax,(_JB_SIGFLAG * 8)(%rdi)
115  pushq %rax
116
117  // Do we need to save the signal mask?
118  testq $1,%rax
119  jz 2f
120
121  // Save current signal mask.
122  pushq %rdi // Push 'env'.
123  // The 'how' argument is ignored if new_mask is NULL.
124  xorq %rsi,%rsi // NULL.
125  leaq (_JB_SIGMASK * 8)(%rdi),%rdx // old_mask.
126  call PIC_PLT(sigprocmask)
127  popq %rdi // Pop 'env'.
128
1292:
130  // Save the callee-save registers.
131  popq %rax
132  andq $-2,%rax
133  movq (%rsp),%r11
134  m_mangle_registers %rax
135  movq %rbx,(_JB_RBX * 8)(%rdi)
136  movq %rbp,(_JB_RBP * 8)(%rdi)
137  movq %r12,(_JB_R12 * 8)(%rdi)
138  movq %r13,(_JB_R13 * 8)(%rdi)
139  movq %r14,(_JB_R14 * 8)(%rdi)
140  movq %r15,(_JB_R15 * 8)(%rdi)
141  movq %rsp,(_JB_RSP * 8)(%rdi)
142  movq %r11,(_JB_PC  * 8)(%rdi)
143  m_unmangle_registers %rax
144
145  m_calculate_checksum %rax, %rdi
146  movq %rax, (_JB_CHECKSUM * 8)(%rdi)
147
148  xorl %eax,%eax
149  ret
150END(sigsetjmp)
151
152// void siglongjmp(sigjmp_buf env, int value);
153ENTRY(siglongjmp)
154__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
155  movq %rdi,%r12
156  pushq %rsi // Push 'value'.
157
158  m_calculate_checksum %rax, %rdi
159  xorq (_JB_CHECKSUM * 8)(%rdi), %rax
160  jnz 3f
161
162  // Do we need to restore the signal mask?
163  movq (_JB_SIGFLAG * 8)(%rdi), %rdi
164  pushq %rdi // Push cookie
165  testq $1, %rdi
166  jz 2f
167
168  // Restore the signal mask.
169  movq $2,%rdi // SIG_SETMASK.
170  leaq (_JB_SIGMASK * 8)(%r12),%rsi // new_mask.
171  xorq %rdx,%rdx // NULL.
172  call PIC_PLT(sigprocmask)
173
1742:
175  // Fetch the setjmp cookie and clear the signal flag bit.
176  popq %rcx
177  andq $-2, %rcx
178
179  popq %rax // Pop 'value'.
180
181  // Restore the callee-save registers.
182  movq (_JB_RBX * 8)(%r12),%rbx
183  movq (_JB_RBP * 8)(%r12),%rbp
184  movq (_JB_R13 * 8)(%r12),%r13
185  movq (_JB_R14 * 8)(%r12),%r14
186  movq (_JB_R15 * 8)(%r12),%r15
187  movq (_JB_RSP * 8)(%r12),%rsp
188  movq (_JB_PC  * 8)(%r12),%r11
189  movq (_JB_R12 * 8)(%r12),%r12
190  m_unmangle_registers %rcx
191
192  // Check the cookie.
193  pushq %rax
194  pushq %r11
195  movq %rcx, %rdi
196  call PIC_PLT(__bionic_setjmp_cookie_check)
197  popq %r11
198  popq %rax
199
200  // Return 1 if value is 0.
201  testl %eax,%eax
202  jnz 1f
203  incl %eax
2041:
205  movq %r11,0(%rsp)
206  ret
207
2083:
209  call PIC_PLT(__bionic_setjmp_checksum_mismatch)
210END(siglongjmp)
211
212ALIAS_SYMBOL(longjmp, siglongjmp)
213__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
214ALIAS_SYMBOL(_longjmp, siglongjmp)
215__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
216