]>
git.saurik.com Git - apple/libplatform.git/blob - private/os/crashlog_private.h
8368c117b2aa5f6b9e93b3b7f0c4a0ed9a13f68e
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
21 #ifndef __OS_CRASHLOG_PRIVATE__
22 #define __OS_CRASHLOG_PRIVATE__
24 #include <os/base_private.h>
26 #if __has_include(<CrashReporterClient.h>)
27 #include <CrashReporterClient.h>
29 #if defined(__x86_64__)
31 #define __os_set_crash_log_cause_and_message(ac, msg) \
32 ({ long _ac = (long)(ac); __asm__ ( \
33 "mov %[_msg], %[_cr_msg]\n\t" \
34 "mov %[_ac], %[_cr_ac]" \
35 : [_ac] "+&a" (_ac), \
36 [_cr_msg] "=m" (gCRAnnotations.message), \
37 [_cr_ac] "=m" (gCRAnnotations.abort_cause) \
38 : [_msg] "r" (("" msg)) \
40 #define _os_set_crash_log_message(msg) \
41 ({ long _clbr; __asm__ ( \
42 "mov %[_msg], %[_cr_msg]" \
44 [_cr_msg] "=m" (gCRAnnotations.message) \
45 : [_msg] "r" (("" msg)) \
48 #elif defined(__arm__)
50 #define __os_set_crash_log_cause_and_message_impl(msg, ac_expr, set_cause, ...) \
51 ({ ac_expr; __asm__( \
52 "push {r9, r10}\n\t" \
54 "movw r9, :lower16:(%[_msg] - 1f - 4)\n\t" \
55 "movt r9, :upper16:(%[_msg] - 1f - 4)\n" \
59 "movw r10, :lower16:(3f - 2f - 4)\n\t" \
60 "movt r10, :upper16:(3f - 2f - 4)\n" \
63 "ldr r10, [r10]\n\t" \
65 "str r9, [r10, %[_msgo]]\n\t" \
67 "str r9, [r10, %[_msgo] + 4]\n\t" \
71 ".non_lazy_symbol_pointer\n" \
73 ".indirect_symbol _gCRAnnotations\n\t" \
76 :: [_msgo] "i" (__builtin_offsetof(typeof(gCRAnnotations), message)), \
77 [_msg] "i" (("" msg)), \
80 #define __os_set_crash_log_cause_and_message(ac, msg) \
81 __os_set_crash_log_cause_and_message_impl(msg, \
82 register long _ac asm("r8") = (long)(ac), \
83 "strd %[_ac], r9, [r10, %[_aco]]\n\t", \
84 [_aco] "i" (__builtin_offsetof(typeof(gCRAnnotations), abort_cause)), \
86 #define _os_set_crash_log_message(msg) \
87 __os_set_crash_log_cause_and_message_impl(msg, (void)0, "")
89 #elif defined(__arm64__)
91 #define __os_set_crash_log_cause_and_message_impl(msg, ac_expr, set_cause, ...) \
92 ({ ac_expr; __asm__( \
93 "stp x20, x21, [sp, #-16]!\n\t" \
94 "adrp x20, %[_msg]@PAGE\n\t" \
95 "add x20, x20, %[_msg]@PAGEOFF\n\t" \
96 "adrp x21, %[_cr]@PAGE\n\t" \
97 "add x21, x21, %[_cr]@PAGEOFF\n\t" \
98 "str x20, [x21, %[_msgo]]\n\t" \
100 "ldp x20, x21, [sp], #16" \
101 :: [_cr] "i" (&gCRAnnotations), \
102 [_msgo] "i" (__builtin_offsetof(typeof(gCRAnnotations), message)), \
103 [_msg] "i" (("" msg)), \
106 #define __os_set_crash_log_cast_ac(ac) \
108 const void *: (uint64_t)(uintptr_t)(ac), \
109 void *: (uint64_t)(uintptr_t)(ac), \
110 default: (uint64_t)(ac))
112 #define __os_set_crash_log_cause_and_message(ac, msg) \
113 __os_set_crash_log_cause_and_message_impl(msg, \
114 register uint64_t _ac asm("x8") = __os_set_crash_log_cast_ac(ac), \
115 "str %[_ac], [x21, %[_aco]]\n\t", \
116 [_aco] "i" (__builtin_offsetof(typeof(gCRAnnotations), abort_cause)), \
118 #define _os_set_crash_log_message(msg) \
119 __os_set_crash_log_cause_and_message_impl(msg, (void)0, "")
122 #define __os_set_crash_log_cause_and_message(ac, msg) ({ \
123 gCRAnnotations.abort_cause = (uint64_t)(int64_t)(ac); \
124 CRSetCrashLogMessage(msg); \
126 #define _os_set_crash_log_message(msg) CRSetCrashLogMessage(msg)
130 * @macro _os_set_crash_log_cause_and_message
133 * Set an abort cause and message before likely crash.
136 * This macro is really meant to minimize register clobbering making sure that
137 * the context is minimally touched.
139 * - On Intel, %rax is used to store the abort cause
140 * - On arm and arm64, r8/x8 is used to store the abort cause, other registers
141 * are left untouched.
143 * An excellent way to use this macro is for example using a wrapper such
147 * OS_NOINLINE OS_NORETURN OS_COLD
149 * _my_type_corruption_abort(my_type_t object OS_UNUSED,
150 * my_other_type_t other OS_UNUSED, long code)
152 * _os_set_crash_log_cause_and_message(code, "object is corrupt");
157 * That wrapper when used:
158 * - is understood as being unlikely and never inlined (OS_COLD OS_NOINLINE)
159 * - captures the address of @a object as well as the one of the companion
160 * object @a other in registers that are easy to introspect in crash traces
161 * - captures the abort cause / error code
164 * The abort cause to set. If it is statically provably 0, then it's ignored.
165 * If the argument type is narrower than long, then it is sign-extended to long.
168 * The static string message to set
170 #define _os_set_crash_log_cause_and_message(ac, msg) \
171 __builtin_choose_expr(os_is_compile_time_constant(!(ac)), ({ \
173 __os_set_crash_log_cause_and_message(ac, msg); \
175 _os_set_crash_log_message(msg); \
176 } }), __os_set_crash_log_cause_and_message(ac, msg))
178 #define _os_set_crash_log_message_dynamic(msg) CRSetCrashLogMessage(msg)
182 #define _os_set_crash_log_cause_and_message(ac, msg) ((void)(ac), (void)(msg))
183 #define _os_set_crash_log_message(msg) ((void)(msg))
184 #define _os_set_crash_log_message_dynamic(msg) ((void)(msg))
186 #endif // __has_include(<CrashReporterClient.h>)
189 * @macro OS_BUG_INTERNAL
192 * Perform a register-preserving crash due to invalid library invariants.
195 * The abort cause to set (see _os_set_crash_log_cause_and_message).
198 * The name of the library.
201 * The static string message to append.
203 #define OS_BUG_INTERNAL(ac, lib, msg) ({ \
204 _os_set_crash_log_cause_and_message(ac, "BUG IN " lib ": " msg); \
205 os_prevent_tail_call_optimization(); \
210 * @macro OS_BUG_CLIENT
213 * Perform a register-preserving crash due to an API misuse by a library client.
216 * The abort cause to set (see _os_set_crash_log_cause_and_message).
219 * The name of the library.
222 * The static string message to append.
224 #define OS_BUG_CLIENT(ac, lib, msg) ({ \
225 _os_set_crash_log_cause_and_message(ac, "BUG IN CLIENT OF " lib ": " msg); \
226 os_prevent_tail_call_optimization(); \
230 #endif // __OS_CRASHLOG_PRIVATE__