]>
Commit | Line | Data |
---|---|---|
ec8f0a04 | 1 | /* |
2fbbb8fa | 2 | * Copyright (c) 2007, 2008, 2011-2013 Apple Inc. All rights reserved. |
ec8f0a04 A |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
b8ce8438 | 5 | * |
ec8f0a04 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
b8ce8438 | 14 | * |
ec8f0a04 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
b8ce8438 | 17 | * |
ec8f0a04 A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
b8ce8438 | 25 | * |
ec8f0a04 A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
ec8f0a04 | 28 | |
9acf5127 | 29 | #include <TargetConditionals.h> // for TARGET_OS_* |
ec8f0a04 | 30 | |
2fbbb8fa A |
31 | #include <stddef.h> |
32 | #include <stdlib.h> | |
b8ce8438 A |
33 | #include <unistd.h> |
34 | #include <corecrypto/cc_priv.h> | |
2fbbb8fa | 35 | #include <libc_private.h> |
afef526e A |
36 | #include <pthread.h> |
37 | #include <pthread/private.h> | |
b8ce8438 | 38 | #if !TARGET_OS_DRIVERKIT |
ec8f0a04 | 39 | #include <dlfcn.h> |
a08f8358 | 40 | #include <os/variant_private.h> |
b8ce8438 | 41 | #endif |
c06d156a | 42 | #include <fcntl.h> |
bdffa7b9 | 43 | #include <errno.h> |
b8ce8438 | 44 | #include <sys/kdebug.h> |
2fbbb8fa | 45 | #include <_libkernel_init.h> // Must be after voucher_private.h |
b8ce8438 | 46 | #include <malloc_implementation.h> |
ec8f0a04 | 47 | |
9acf5127 A |
48 | #include <mach-o/dyld_priv.h> |
49 | ||
ec8f0a04 | 50 | // system library initialisers |
afef526e A |
51 | extern void mach_init(void); // from libsystem_kernel.dylib |
52 | extern void __libplatform_init(void *future_use, const char *envp[], const char *apple[], const struct ProgramVars *vars); | |
53 | extern void __pthread_init(const struct _libpthread_functions *libpthread_funcs, const char *envp[], const char *apple[], const struct ProgramVars *vars); // from libsystem_pthread.dylib | |
afef526e A |
54 | extern void __malloc_init(const char *apple[]); // from libsystem_malloc.dylib |
55 | extern void __keymgr_initializer(void); // from libkeymgr.dylib | |
56 | extern void _dyld_initializer(void); // from libdyld.dylib | |
57 | extern void libdispatch_init(void); // from libdispatch.dylib | |
58 | extern void _libxpc_initializer(void); // from libxpc.dylib | |
2fbbb8fa | 59 | extern void _libsecinit_initializer(void); // from libsecinit.dylib |
9acf5127 | 60 | extern void _libtrace_init(void); // from libsystem_trace.dylib |
2ccc3113 | 61 | extern void _container_init(const char *apple[]); // from libsystem_containermanager.dylib |
706576d5 | 62 | extern void __libdarwin_init(void); // from libsystem_darwin.dylib |
2fbbb8fa | 63 | |
ec8f0a04 | 64 | |
2fbbb8fa A |
65 | // clear qos tsd (from pthread) |
66 | extern void _pthread_clear_qos_tsd(mach_port_t) __attribute__((weak_import)); | |
67 | ||
ec8f0a04 | 68 | // system library atfork handlers |
1c91c7f1 A |
69 | extern void _pthread_atfork_prepare(void); |
70 | extern void _pthread_atfork_parent(void); | |
71 | extern void _pthread_atfork_child(void); | |
2ccc3113 A |
72 | extern void _pthread_atfork_prepare_handlers(); |
73 | extern void _pthread_atfork_parent_handlers(void); | |
74 | extern void _pthread_atfork_child_handlers(void); | |
2fbbb8fa | 75 | extern void _pthread_exit_if_canceled(int); |
afef526e A |
76 | |
77 | extern void dispatch_atfork_prepare(void); | |
78 | extern void dispatch_atfork_parent(void); | |
79 | extern void dispatch_atfork_child(void); | |
80 | ||
9acf5127 A |
81 | extern void _libtrace_fork_child(void); |
82 | ||
afef526e A |
83 | extern void _malloc_fork_prepare(void); |
84 | extern void _malloc_fork_parent(void); | |
85 | extern void _malloc_fork_child(void); | |
bdffa7b9 A |
86 | |
87 | extern void _mach_fork_child(void); | |
bdffa7b9 | 88 | extern void _notify_fork_child(void); |
b8ce8438 A |
89 | extern void _dyld_atfork_prepare(void); |
90 | extern void _dyld_atfork_parent(void); | |
bdffa7b9 A |
91 | extern void _dyld_fork_child(void); |
92 | extern void xpc_atfork_prepare(void); | |
93 | extern void xpc_atfork_parent(void); | |
94 | extern void xpc_atfork_child(void); | |
afef526e A |
95 | extern void _libSC_info_fork_prepare(void); |
96 | extern void _libSC_info_fork_parent(void); | |
97 | extern void _libSC_info_fork_child(void); | |
98 | extern void _asl_fork_child(void); | |
ec8f0a04 | 99 | |
2fbbb8fa A |
100 | #if defined(HAVE_SYSTEM_CORESERVICES) |
101 | // libsystem_coreservices.dylib | |
102 | extern void _libcoreservices_fork_child(void); | |
103 | extern char *_dirhelper(int, char *, size_t); | |
104 | #endif | |
105 | ||
ec8f0a04 | 106 | // advance decls for below; |
bdffa7b9 A |
107 | void libSystem_atfork_prepare(void); |
108 | void libSystem_atfork_parent(void); | |
109 | void libSystem_atfork_child(void); | |
ec8f0a04 | 110 | |
a08f8358 | 111 | #if SUPPORT_ASAN |
c06d156a A |
112 | const char *__asan_default_options(void); |
113 | #endif | |
114 | ||
b8ce8438 A |
115 | static inline void |
116 | _libSystem_ktrace4(uint32_t code, uint64_t a, uint64_t b, uint64_t c, uint64_t d) | |
117 | { | |
118 | if (__builtin_expect(*(volatile uint32_t *)_COMM_PAGE_KDEBUG_ENABLE == 0, 1)) return; | |
119 | kdebug_trace(code, a, b, c, d); | |
120 | } | |
121 | #define _libSystem_ktrace3(code, a, b, c) _libSystem_ktrace4(code, a, b, c, 0) | |
122 | #define _libSystem_ktrace2(code, a, b) _libSystem_ktrace4(code, a, b, 0, 0) | |
123 | #define _libSystem_ktrace1(code, a) _libSystem_ktrace4(code, a, 0, 0, 0) | |
124 | #define _libSystem_ktrace0(code) _libSystem_ktrace4(code, 0, 0, 0, 0) | |
125 | ||
126 | /* | |
127 | * these define stable Ariadne tracepoints. If initializers are removed, or | |
128 | * added, then old tracepoints MUST NOT be recycled. | |
129 | */ | |
130 | enum { | |
131 | ARIADNE_LIFECYCLE_libsystem_init = ARIADNEDBG_CODE(220, 4), | |
132 | }; | |
133 | ||
134 | /* | |
135 | * These represent the initializer "name" | |
136 | * | |
137 | * They happen to match the order of the initializers at some point in time, | |
138 | * but there's no guarantee made that traecepoints will appear in numerical | |
139 | * order. As initializers come and go, new codes shall be allocated, | |
140 | * and no slots reused. | |
141 | */ | |
142 | enum init_func { | |
143 | INIT_SYSTEM = 0, | |
144 | INIT_KERNEL = 1, | |
145 | INIT_PLATFORM = 2, | |
146 | INIT_PTHREAD = 3, | |
147 | INIT_LIBC = 4, | |
148 | INIT_MALLOC = 5, | |
149 | INIT_KEYMGR = 6, | |
150 | INIT_DYLD = 7, | |
151 | INIT_LIBDISPATCH = 8, | |
152 | INIT_LIBXPC = 9, | |
153 | INIT_LIBTRACE = 10, | |
154 | INIT_SECINIT = 11, | |
155 | INIT_CONTAINERMGR = 12, | |
156 | INIT_DARWIN = 13, | |
157 | }; | |
158 | ||
159 | #define _libSystem_ktrace_init_func(what) \ | |
160 | _libSystem_ktrace1(ARIADNE_LIFECYCLE_libsystem_init | DBG_FUNC_NONE, INIT_##what) | |
161 | ||
2fbbb8fa A |
162 | // libsyscall_initializer() initializes all of libSystem.dylib |
163 | // <rdar://problem/4892197> | |
164 | __attribute__((constructor)) | |
165 | static void | |
166 | libSystem_initializer(int argc, | |
167 | const char* argv[], | |
168 | const char* envp[], | |
169 | const char* apple[], | |
170 | const struct ProgramVars* vars) | |
ec8f0a04 | 171 | { |
afef526e | 172 | static const struct _libkernel_functions libkernel_funcs = { |
b12e72ed | 173 | .version = 4, |
2fbbb8fa | 174 | // V1 functions |
b8ce8438 | 175 | #if !TARGET_OS_DRIVERKIT |
ec8f0a04 | 176 | .dlsym = dlsym, |
b8ce8438 | 177 | #endif |
afef526e A |
178 | .malloc = malloc, |
179 | .free = free, | |
180 | .realloc = realloc, | |
181 | ._pthread_exit_if_canceled = _pthread_exit_if_canceled, | |
2fbbb8fa A |
182 | // V2 functions (removed) |
183 | // V3 functions | |
184 | .pthread_clear_qos_tsd = _pthread_clear_qos_tsd, | |
b12e72ed A |
185 | // V4 functions |
186 | .pthread_current_stack_contains_np = pthread_current_stack_contains_np, | |
afef526e A |
187 | }; |
188 | ||
189 | static const struct _libpthread_functions libpthread_funcs = { | |
2fbbb8fa | 190 | .version = 2, |
afef526e | 191 | .exit = exit, |
2fbbb8fa A |
192 | .malloc = malloc, |
193 | .free = free, | |
194 | }; | |
b8ce8438 | 195 | |
2fbbb8fa A |
196 | static const struct _libc_functions libc_funcs = { |
197 | .version = 1, | |
198 | .atfork_prepare = libSystem_atfork_prepare, | |
199 | .atfork_parent = libSystem_atfork_parent, | |
200 | .atfork_child = libSystem_atfork_child, | |
201 | #if defined(HAVE_SYSTEM_CORESERVICES) | |
202 | .dirhelper = _dirhelper, | |
203 | #endif | |
ec8f0a04 | 204 | }; |
b8ce8438 | 205 | |
b8ce8438 | 206 | _libSystem_ktrace0(ARIADNE_LIFECYCLE_libsystem_init | DBG_FUNC_START); |
ec8f0a04 | 207 | |
afef526e | 208 | __libkernel_init(&libkernel_funcs, envp, apple, vars); |
b8ce8438 | 209 | _libSystem_ktrace_init_func(KERNEL); |
ec8f0a04 | 210 | |
afef526e | 211 | __libplatform_init(NULL, envp, apple, vars); |
b8ce8438 | 212 | _libSystem_ktrace_init_func(PLATFORM); |
a8f6861e | 213 | |
afef526e | 214 | __pthread_init(&libpthread_funcs, envp, apple, vars); |
b8ce8438 | 215 | _libSystem_ktrace_init_func(PTHREAD); |
a8f6861e | 216 | |
2fbbb8fa | 217 | _libc_initializer(&libc_funcs, envp, apple, vars); |
b8ce8438 | 218 | _libSystem_ktrace_init_func(LIBC); |
afef526e A |
219 | |
220 | // TODO: Move __malloc_init before __libc_init after breaking malloc's upward link to Libc | |
3186893e | 221 | // Note that __malloc_init() will also initialize ASAN when it is present |
afef526e | 222 | __malloc_init(apple); |
b8ce8438 | 223 | _libSystem_ktrace_init_func(MALLOC); |
afef526e | 224 | |
706576d5 | 225 | #if TARGET_OS_OSX |
2fbbb8fa A |
226 | /* <rdar://problem/9664631> */ |
227 | __keymgr_initializer(); | |
b8ce8438 | 228 | _libSystem_ktrace_init_func(KEYMGR); |
2fbbb8fa A |
229 | #endif |
230 | ||
ec8f0a04 | 231 | _dyld_initializer(); |
b8ce8438 | 232 | _libSystem_ktrace_init_func(DYLD); |
9acf5127 | 233 | |
ec8f0a04 | 234 | libdispatch_init(); |
b8ce8438 A |
235 | _libSystem_ktrace_init_func(LIBDISPATCH); |
236 | ||
237 | #if !TARGET_OS_DRIVERKIT | |
ec8f0a04 | 238 | _libxpc_initializer(); |
b8ce8438 | 239 | _libSystem_ktrace_init_func(LIBXPC); |
bdffa7b9 | 240 | |
a08f8358 | 241 | #if SUPPORT_ASAN |
c06d156a A |
242 | setenv("DT_BYPASS_LEAKS_CHECK", "1", 1); |
243 | #endif | |
b8ce8438 | 244 | #endif // !TARGET_OS_DRIVERKIT |
c06d156a | 245 | |
2ccc3113 A |
246 | // must be initialized after dispatch |
247 | _libtrace_init(); | |
b8ce8438 | 248 | _libSystem_ktrace_init_func(LIBTRACE); |
2ccc3113 | 249 | |
b8ce8438 A |
250 | #if !TARGET_OS_DRIVERKIT |
251 | #if defined(HAVE_SYSTEM_SECINIT) | |
2fbbb8fa | 252 | _libsecinit_initializer(); |
b8ce8438 | 253 | _libSystem_ktrace_init_func(SECINIT); |
2fbbb8fa A |
254 | #endif |
255 | ||
a85a94cf | 256 | #if defined(HAVE_SYSTEM_CONTAINERMANAGER) |
2ccc3113 | 257 | _container_init(apple); |
b8ce8438 | 258 | _libSystem_ktrace_init_func(CONTAINERMGR); |
2ccc3113 A |
259 | #endif |
260 | ||
706576d5 | 261 | __libdarwin_init(); |
b8ce8438 A |
262 | _libSystem_ktrace_init_func(DARWIN); |
263 | #endif // !TARGET_OS_DRIVERKIT | |
706576d5 | 264 | |
a08f8358 A |
265 | const struct _malloc_late_init mli = { |
266 | .version = 1, | |
267 | #if !TARGET_OS_DRIVERKIT | |
268 | .dlopen = dlopen, | |
269 | .dlsym = dlsym, | |
270 | // this must come after _libxpc_initializer() | |
271 | .internal_diagnostics = os_variant_has_internal_diagnostics("com.apple.libsystem"), | |
272 | #endif | |
273 | }; | |
274 | ||
275 | __malloc_late_init(&mli); | |
bdffa7b9 | 276 | |
9acf5127 | 277 | #if !TARGET_OS_IPHONE |
b8ce8438 A |
278 | /* <rdar://problem/22139800> - Preserve the old behavior of apple[] for |
279 | * programs that haven't linked against newer SDK. | |
9acf5127 A |
280 | */ |
281 | #define APPLE0_PREFIX "executable_path=" | |
282 | if (dyld_get_program_sdk_version() < DYLD_MACOSX_VERSION_10_11){ | |
283 | if (strncmp(apple[0], APPLE0_PREFIX, strlen(APPLE0_PREFIX)) == 0){ | |
284 | apple[0] = apple[0] + strlen(APPLE0_PREFIX); | |
285 | } | |
286 | } | |
287 | #endif | |
2fbbb8fa | 288 | |
3186893e A |
289 | #if TARGET_OS_OSX && !defined(__i386__) |
290 | bool enable_system_version_compat = false; | |
291 | bool enable_ios_version_compat = false; | |
292 | char *system_version_compat_override = getenv("SYSTEM_VERSION_COMPAT"); | |
293 | if (system_version_compat_override != NULL) { | |
294 | long override = strtol(system_version_compat_override, NULL, 0); | |
295 | if (override == 1) { | |
296 | enable_system_version_compat = true; | |
297 | } else if (override == 2) { | |
298 | enable_ios_version_compat = true; | |
299 | } | |
300 | } else if (dyld_get_active_platform() == PLATFORM_MACCATALYST) { | |
301 | if (!dyld_program_sdk_at_least(dyld_platform_version_iOS_14_0)) { | |
302 | enable_system_version_compat = true; | |
303 | } | |
304 | } else if (dyld_get_active_platform() == PLATFORM_IOS) { | |
305 | enable_ios_version_compat = true; | |
306 | } else if (!dyld_program_sdk_at_least(dyld_platform_version_macOS_10_16)) { | |
307 | enable_system_version_compat = true; | |
308 | } | |
309 | ||
310 | if (enable_system_version_compat || enable_ios_version_compat) { | |
311 | struct _libkernel_late_init_config config = { | |
312 | .version = 2, | |
313 | .enable_system_version_compat = enable_system_version_compat, | |
314 | .enable_ios_version_compat = enable_ios_version_compat, | |
315 | }; | |
316 | __libkernel_init_late(&config); | |
317 | } | |
318 | #endif // TARGET_OS_OSX && !defined(__i386__) | |
319 | ||
b8ce8438 A |
320 | _libSystem_ktrace0(ARIADNE_LIFECYCLE_libsystem_init | DBG_FUNC_END); |
321 | ||
bdffa7b9 A |
322 | /* <rdar://problem/11588042> |
323 | * C99 standard has the following in section 7.5(3): | |
324 | * "The value of errno is zero at program startup, but is never set | |
325 | * to zero by any library function." | |
326 | */ | |
327 | errno = 0; | |
ec8f0a04 A |
328 | } |
329 | ||
330 | /* | |
2fbbb8fa | 331 | * libSystem_atfork_{prepare,parent,child}() are called by libc during fork(2). |
ec8f0a04 | 332 | */ |
2fbbb8fa A |
333 | void |
334 | libSystem_atfork_prepare(void) | |
ec8f0a04 | 335 | { |
2ccc3113 A |
336 | // first call client prepare handlers registered with pthread_atfork() |
337 | _pthread_atfork_prepare_handlers(); | |
338 | ||
339 | // second call hardwired fork prepare handlers for Libsystem components | |
340 | // in the _reverse_ order of library initalization above | |
b8ce8438 | 341 | #if !TARGET_OS_DRIVERKIT |
afef526e | 342 | _libSC_info_fork_prepare(); |
ec8f0a04 | 343 | xpc_atfork_prepare(); |
b8ce8438 | 344 | #endif // !TARGET_OS_DRIVERKIT |
afef526e | 345 | dispatch_atfork_prepare(); |
b8ce8438 A |
346 | _dyld_atfork_prepare(); |
347 | cc_atfork_prepare(); | |
afef526e | 348 | _malloc_fork_prepare(); |
1c91c7f1 | 349 | _pthread_atfork_prepare(); |
ec8f0a04 A |
350 | } |
351 | ||
2fbbb8fa A |
352 | void |
353 | libSystem_atfork_parent(void) | |
ec8f0a04 | 354 | { |
2ccc3113 A |
355 | // first call hardwired fork parent handlers for Libsystem components |
356 | // in the order of library initalization above | |
1c91c7f1 | 357 | _pthread_atfork_parent(); |
2ccc3113 | 358 | _malloc_fork_parent(); |
b8ce8438 A |
359 | cc_atfork_parent(); |
360 | _dyld_atfork_parent(); | |
afef526e | 361 | dispatch_atfork_parent(); |
b8ce8438 | 362 | #if !TARGET_OS_DRIVERKIT |
ec8f0a04 | 363 | xpc_atfork_parent(); |
afef526e | 364 | _libSC_info_fork_parent(); |
b8ce8438 | 365 | #endif // !TARGET_OS_DRIVERKIT |
2ccc3113 A |
366 | |
367 | // second call client parent handlers registered with pthread_atfork() | |
368 | _pthread_atfork_parent_handlers(); | |
ec8f0a04 A |
369 | } |
370 | ||
2fbbb8fa A |
371 | void |
372 | libSystem_atfork_child(void) | |
ec8f0a04 | 373 | { |
2ccc3113 A |
374 | // first call hardwired fork child handlers for Libsystem components |
375 | // in the order of library initalization above | |
2ccc3113 | 376 | _mach_fork_child(); |
b8ce8438 | 377 | _pthread_atfork_child(); |
afef526e | 378 | _malloc_fork_child(); |
b8ce8438 | 379 | cc_atfork_child(); |
2ccc3113 | 380 | _libc_fork_child(); // _arc4_fork_child calls malloc |
b8ce8438 | 381 | _dyld_fork_child(); |
afef526e | 382 | dispatch_atfork_child(); |
b8ce8438 | 383 | #if !TARGET_OS_DRIVERKIT |
2fbbb8fa A |
384 | #if defined(HAVE_SYSTEM_CORESERVICES) |
385 | _libcoreservices_fork_child(); | |
386 | #endif | |
afef526e | 387 | _asl_fork_child(); |
ec8f0a04 | 388 | _notify_fork_child(); |
ec8f0a04 | 389 | xpc_atfork_child(); |
b8ce8438 | 390 | #endif // !TARGET_OS_DRIVERKIT |
2ccc3113 | 391 | _libtrace_fork_child(); |
b8ce8438 | 392 | #if !TARGET_OS_DRIVERKIT |
afef526e | 393 | _libSC_info_fork_child(); |
b8ce8438 | 394 | #endif // !TARGET_OS_DRIVERKIT |
ec8f0a04 | 395 | |
2ccc3113 A |
396 | // second call client parent handlers registered with pthread_atfork() |
397 | _pthread_atfork_child_handlers(); | |
ec8f0a04 A |
398 | } |
399 | ||
a08f8358 A |
400 | #if SUPPORT_ASAN |
401 | ||
402 | // Prevents use of coloring terminal signals in report. These | |
403 | // hinder readability when writing to files or the system log. | |
404 | #define ASAN_OPT_NO_COLOR "color=never" | |
405 | ||
406 | // Disables ASan's signal handlers. It's better to let the system catch | |
407 | // these kinds of crashes. | |
408 | #define ASAN_OPT_NO_SIGNAL_HANDLERS ":handle_segv=0:handle_sigbus=0:handle_sigill=0:handle_sigfpe=0" | |
409 | ||
410 | // Disables using the out-of-process symbolizer (atos) but still allows | |
411 | // in-process symbolization via `dladdr()`. This gives useful function names | |
412 | // (unless they are redacted) which can be helpful in the event we can't | |
413 | // symbolize offline. Out-of-process symbolization isn't useful because | |
414 | // the dSYMs are usually not present on the device. | |
415 | #define ASAN_OPT_NO_OOP_SYMBOLIZER ":external_symbolizer_path=" | |
416 | ||
417 | // Don't try to log to a file. It's difficult to find a location for the file | |
418 | // that is writable so just write to stderr. | |
419 | #define ASAN_OPT_FILE_LOG ":log_path=stderr:log_exe_name=0" | |
420 | ||
421 | // Print the module map when finding an issue. This is necessary for offline | |
422 | // symbolication. | |
423 | #define ASAN_OPT_MODULE_MAP ":print_module_map=2" | |
424 | ||
425 | // Disable ODR violation checking. | |
426 | // <rdar://problem/71021707> Investigate enabling ODR checking for ASan in BATS and in the `_asan` variant | |
427 | #define ASAN_OPT_NO_ODR_VIOLATION ":detect_odr_violation=0" | |
428 | ||
429 | // Start ASan in deactivated mode. This reduces memory overhead until | |
430 | // instrumented code is loaded. This prevents catching bugs if no instrumented | |
431 | // code is loaded. | |
432 | #define ASAN_OPT_START_DEACTIVATED ":start_deactivated=1" | |
433 | ||
434 | // Do not crash when an error is found. This always works for errors caught via | |
435 | // ASan's interceptors. This won't work for errors caught in ASan | |
436 | // instrumentation unless the code is compiled with | |
437 | // `-fsanitize-recover=address`. If this option is being used then the ASan | |
438 | // reports can only be found by looking at the system log. | |
439 | #define ASAN_OPT_NO_HALT_ON_ERROR ":halt_on_error=0" | |
440 | ||
441 | // Crash when an error is found. | |
442 | #define ASAN_OPT_HALT_ON_ERROR ":halt_on_error=1" | |
443 | ||
444 | // ASan options common to all supported variants | |
445 | #define COMMON_ASAN_OPTIONS \ | |
446 | ASAN_OPT_NO_COLOR \ | |
447 | ASAN_OPT_NO_SIGNAL_HANDLERS \ | |
448 | ASAN_OPT_NO_OOP_SYMBOLIZER \ | |
449 | ASAN_OPT_FILE_LOG \ | |
450 | ASAN_OPT_MODULE_MAP \ | |
451 | ASAN_OPT_NO_ODR_VIOLATION | |
452 | ||
453 | #if defined(CURRENT_VARIANT_normal) || defined(CURRENT_VARIANT_debug) || defined (CURRENT_VARIANT_no_asan) | |
454 | ||
455 | // In the normal variant ASan will be running in all userspace processes ("whole userspace ASan"). | |
456 | // This mode exists to support "ASan in BATS". | |
457 | // | |
458 | // Supporting ASan in the debug variant preserves existing behavior. | |
459 | // | |
460 | // The no_asan variant does not load the ASan runtime. However, the runtime | |
461 | // might still be loaded if a program or its dependencies are instrumented. | |
462 | // There is nothing we can do to prevent this so we should set the appropriate | |
463 | // ASan options (same as normal variant) if it does happen. We try to do this | |
464 | // here but this currently doesn't work due to rdar://problem/72212914. | |
465 | // | |
466 | // These variants use the following extra options: | |
467 | // | |
468 | // ASAN_OPT_NO_HALT_ON_ERROR - Try to avoid crash loops and increase the | |
469 | // chances of booting successfully. | |
470 | // ASAN_OPT_START_DEACTIVATED - Try to reduce memory overhead. | |
471 | ||
472 | # define DEFAULT_ASAN_OPTIONS \ | |
473 | COMMON_ASAN_OPTIONS \ | |
474 | ASAN_OPT_START_DEACTIVATED \ | |
475 | ASAN_OPT_NO_HALT_ON_ERROR | |
476 | ||
477 | #elif defined(CURRENT_VARIANT_asan) | |
478 | ||
479 | // The `_asan` variant is used to support running proceses with | |
480 | // `DYLD_IMAGE_SUFFIX=_asan`. This mode is typically used to target select parts of the OS. | |
481 | // | |
482 | // It uses the following extra options: | |
483 | // | |
484 | // ASAN_OPT_HALT_ON_ERROR - Crashing is better than just writing the error to the system log | |
485 | // if the system can handle this. This workflow is | |
486 | // more tolerant (e.g. `launchctl debug`) to crashing | |
487 | // than the "whole userspace ASan" workflow. | |
488 | ||
489 | # define DEFAULT_ASAN_OPTIONS \ | |
490 | COMMON_ASAN_OPTIONS \ | |
491 | ASAN_OPT_HALT_ON_ERROR | |
492 | ||
493 | #else | |
494 | # error Supporting ASan is not supported in the current variant | |
495 | #endif | |
496 | ||
c06d156a A |
497 | char dynamic_asan_opts[1024] = {0}; |
498 | const char *__asan_default_options(void) { | |
499 | int fd = open("/System/Library/Preferences/com.apple.asan.options", O_RDONLY); | |
500 | if (fd != -1) { | |
501 | ssize_t remaining_size = sizeof(dynamic_asan_opts) - 1; | |
502 | char *p = dynamic_asan_opts; | |
503 | ssize_t read_bytes = 0; | |
504 | do { | |
505 | read_bytes = read(fd, p, remaining_size); | |
506 | remaining_size -= read_bytes; | |
507 | } while (read_bytes > 0); | |
508 | close(fd); | |
509 | ||
510 | if (dynamic_asan_opts[0]) { | |
511 | return dynamic_asan_opts; | |
512 | } | |
513 | } | |
514 | ||
b8ce8438 | 515 | return DEFAULT_ASAN_OPTIONS; |
c06d156a | 516 | } |
a08f8358 A |
517 | |
518 | #undef ASAN_OPT_NO_COLOR | |
519 | #undef ASAN_OPT_NO_SIGNAL_HANDLERS | |
520 | #undef ASAN_OPT_NO_OOP_SYMBOLIZER | |
521 | #undef ASAN_OPT_FILE_LOG | |
522 | #undef ASAN_OPT_MODULE_MAP | |
523 | #undef ASAN_OPT_NO_ODR_VIOLATION | |
524 | #undef ASAN_OPT_START_DEACTIVATED | |
525 | #undef ASAN_OPT_NO_HALT_ON_ERROR | |
526 | #undef ASAN_OPT_HALT_ON_ERROR | |
527 | ||
528 | #undef COMMON_ASAN_OPTIONS | |
529 | #undef DEFAULT_ASAN_OPTIONS | |
530 | ||
c06d156a A |
531 | #endif |
532 | ||
b8ce8438 | 533 | /* |
ec8f0a04 A |
534 | * Old crt1.o glue used to call through mach_init_routine which was used to initialize libSystem. |
535 | * LibSystem now auto-initializes but mach_init_routine is left for binary compatibility. | |
536 | */ | |
bdffa7b9 | 537 | static void mach_init_old(void) {} |
ec8f0a04 A |
538 | void (*mach_init_routine)(void) = &mach_init_old; |
539 | ||
540 | /* | |
541 | * This __crashreporter_info__ symbol is for all non-dylib parts of libSystem. | |
542 | */ | |
543 | const char *__crashreporter_info__; | |
544 | asm (".desc __crashreporter_info__, 0x10"); |