1/******************************************************************************
2 * Copyright © 2018, VideoLAN and dav1d authors
3 * Copyright © 2015 Martin Storsjo
4 * Copyright © 2015 Janne Grunau
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 *    list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 *    this list of conditions and the following disclaimer in the documentation
15 *    and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/
28
29#define PRIVATE_PREFIX checkasm_
30
31#include "src/arm/asm.S"
32#include "src/arm/64/util.S"
33
34const register_init, align=4
35        .quad 0x21f86d66c8ca00ce
36        .quad 0x75b6ba21077c48ad
37        .quad 0xed56bb2dcb3c7736
38        .quad 0x8bda43d3fd1a7e06
39        .quad 0xb64a9c9e5d318408
40        .quad 0xdf9a54b303f1d3a3
41        .quad 0x4a75479abd64e097
42        .quad 0x249214109d5d1c88
43        .quad 0x1a1b2550a612b48c
44        .quad 0x79445c159ce79064
45        .quad 0x2eed899d5a28ddcd
46        .quad 0x86b2536fcd8cf636
47        .quad 0xb0856806085e7943
48        .quad 0x3f2bf84fc0fcca4e
49        .quad 0xacbd382dcf5b8de2
50        .quad 0xd229e1f5b281303f
51        .quad 0x71aeaff20b095fd9
52        .quad 0xab63e2e11fa38ed9
53endconst
54
55
56const error_message_register
57        .asciz "failed to preserve register"
58error_message_stack:
59        .asciz "stack clobbered"
60endconst
61
62
63// max number of args used by any asm function.
64#define MAX_ARGS 15
65
66#define CLOBBER_STACK ((8*MAX_ARGS + 15) & ~15)
67
68function stack_clobber, export=1
69        mov             x3,  sp
70        mov             x2,  #CLOBBER_STACK
711:
72        stp             x0,  x1,  [sp, #-16]!
73        subs            x2,  x2,  #16
74        b.gt            1b
75        mov             sp,  x3
76        ret
77endfunc
78
79// + 16 for stack canary reference
80#define ARG_STACK ((8*(MAX_ARGS - 8) + 15) & ~15 + 16)
81
82function checked_call, export=1
83        stp             x29, x30, [sp, #-16]!
84        mov             x29, sp
85        stp             x19, x20, [sp, #-16]!
86        stp             x21, x22, [sp, #-16]!
87        stp             x23, x24, [sp, #-16]!
88        stp             x25, x26, [sp, #-16]!
89        stp             x27, x28, [sp, #-16]!
90        stp             d8,  d9,  [sp, #-16]!
91        stp             d10, d11, [sp, #-16]!
92        stp             d12, d13, [sp, #-16]!
93        stp             d14, d15, [sp, #-16]!
94
95        movrel          x9, register_init
96        ldp             d8,  d9,  [x9], #16
97        ldp             d10, d11, [x9], #16
98        ldp             d12, d13, [x9], #16
99        ldp             d14, d15, [x9], #16
100        ldp             x19, x20, [x9], #16
101        ldp             x21, x22, [x9], #16
102        ldp             x23, x24, [x9], #16
103        ldp             x25, x26, [x9], #16
104        ldp             x27, x28, [x9], #16
105
106        sub             sp,  sp,  #ARG_STACK
107.equ pos, 0
108.rept MAX_ARGS-8
109        // Skip the first 8 args, that are loaded into registers
110        ldr             x9, [x29, #16 + 8*8 + pos]
111        str             x9, [sp, #pos]
112.equ pos, pos + 8
113.endr
114
115        // Fill x8-x17 with garbage. This doesn't have to be preserved,
116        // but avoids relying on them having any particular value.
117        movrel          x9, register_init
118        ldp             x10, x11, [x9], #32
119        ldp             x12, x13, [x9], #32
120        ldp             x14, x15, [x9], #32
121        ldp             x16, x17, [x9], #32
122        ldp             x8,  x9,  [x9]
123
124        // For stack overflows, the callee is free to overwrite the parameters
125        // that were passed on the stack (if any), so we can only check after
126        // that point. First figure out how many parameters the function
127        // really took on the stack:
128        ldr             w2,  [x29, #16 + 8*8 + (MAX_ARGS-8)*8]
129        // Load the first non-parameter value from the stack, that should be
130        // left untouched by the function. Store a copy of it inverted, so that
131        // e.g. overwriting everything with zero would be noticed.
132        ldr             x2,  [sp, x2, lsl #3]
133        mvn             x2,  x2
134        str             x2,  [sp, #ARG_STACK-8]
135
136        // Load the in-register arguments
137        mov             x12, x0
138        ldp             x0,  x1,  [x29, #16]
139        ldp             x2,  x3,  [x29, #32]
140        ldp             x4,  x5,  [x29, #48]
141        ldp             x6,  x7,  [x29, #64]
142        // Call the target function
143        blr             x12
144
145        // Load the number of stack parameters, stack canary and its reference
146        ldr             w2,  [x29, #16 + 8*8 + (MAX_ARGS-8)*8]
147        ldr             x2,  [sp, x2, lsl #3]
148        ldr             x3,  [sp, #ARG_STACK-8]
149
150        add             sp,  sp,  #ARG_STACK
151        stp             x0,  x1,  [sp, #-16]!
152
153        mvn             x3,  x3
154        cmp             x2,  x3
155        b.ne            2f
156
157        movrel          x9, register_init
158        movi            v3.8h,  #0
159
160.macro check_reg_neon reg1, reg2
161        ldr             q1,  [x9], #16
162        uzp1            v2.2d,  v\reg1\().2d, v\reg2\().2d
163        eor             v1.16b, v1.16b, v2.16b
164        orr             v3.16b, v3.16b, v1.16b
165.endm
166        check_reg_neon  8,  9
167        check_reg_neon  10, 11
168        check_reg_neon  12, 13
169        check_reg_neon  14, 15
170        uqxtn           v3.8b,  v3.8h
171        umov            x3,  v3.d[0]
172
173.macro check_reg reg1, reg2
174        ldp             x0,  x1,  [x9], #16
175        eor             x0,  x0,  \reg1
176        eor             x1,  x1,  \reg2
177        orr             x3,  x3,  x0
178        orr             x3,  x3,  x1
179.endm
180        check_reg       x19, x20
181        check_reg       x21, x22
182        check_reg       x23, x24
183        check_reg       x25, x26
184        check_reg       x27, x28
185
186        cbz             x3,  0f
187
188        movrel          x0, error_message_register
189        b               1f
1902:
191        movrel          x0, error_message_stack
1921:
193#ifdef PREFIX
194        bl              _checkasm_fail_func
195#else
196        bl              checkasm_fail_func
197#endif
1980:
199        ldp             x0,  x1,  [sp], #16
200        ldp             d14, d15, [sp], #16
201        ldp             d12, d13, [sp], #16
202        ldp             d10, d11, [sp], #16
203        ldp             d8,  d9,  [sp], #16
204        ldp             x27, x28, [sp], #16
205        ldp             x25, x26, [sp], #16
206        ldp             x23, x24, [sp], #16
207        ldp             x21, x22, [sp], #16
208        ldp             x19, x20, [sp], #16
209        ldp             x29, x30, [sp], #16
210        ret
211endfunc
212