]> git.saurik.com Git - apple/libc.git/blobdiff - os/assumes.c
Libc-1439.40.11.tar.gz
[apple/libc.git] / os / assumes.c
index 9950166db5fb2010bffd7c29514de16335bee094..389fe17fce53f61460830d7cca11f034fdffba19 100644 (file)
  * @APPLE_LICENSE_HEADER_END@
  */
 
-#include <dispatch/dispatch.h>
+#include <TargetConditionals.h>
 #include <uuid/uuid.h>
 #include <sys/types.h>
 #include <sys/sysctl.h>
 #include <mach-o/loader.h>
 #include <mach-o/fat.h>
-#include <mach-o/arch.h>
 #include <mach-o/getsect.h>
 #include <pthread.h>
 #include <sys/types.h>
+#include <sys/reason.h>
+#include <unistd.h>
 #include <execinfo.h>
 #include <stdio.h>
-#include <dlfcn.h>
 #include <_simple.h>
 #include <errno.h>
 #include <pthread.h>
 #include <string.h>
 #include "os/assumes.h"
-#include "gen/assumes.h"
-#include <os/trace.h>
+
+#if !TARGET_OS_DRIVERKIT
+#include <dlfcn.h>
+#include <os/debug_private.h>
+#include <os/log.h>
+#include <os/log_private.h>
+#include <os/reason_private.h>
+#else
+#define _os_debug_log_error_str(...)
+// placeholder to disable usage of dlfcn.h
+typedef struct dl_info {
+       void *dli_fbase;
+} Dl_info;
+#endif
+#if __has_include(<CrashReporterClient.h>)
+#include <CrashReporterClient.h>
+#define os_set_crash_message(arg) CRSetCrashLogMessage(arg)
+#else
+#define os_set_crash_message(arg)
+#endif
 
 #define OSX_ASSUMES_LOG_REDIRECT_SECT_NAME "__osx_log_func"
 #define os_atomic_cmpxchg(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
 
-static bool _os_should_abort_on_assumes = false;
-
+#if !TARGET_OS_DRIVERKIT
 static const char *
 _os_basename(const char *p)
 {
        return ((strrchr(p, '/') ? : p - 1) + 1);
 }
+#endif
 
 static void
 _os_get_build(char *build, size_t sz)
@@ -68,8 +86,16 @@ _os_get_build(char *build, size_t sz)
        if (r == 0 && sz == 1) {
                (void)strlcpy(build, "99Z999", oldsz);
        }
+#if TARGET_IPHONE_SIMULATOR
+        char *simVersion = getenv("SIMULATOR_RUNTIME_BUILD_VERSION");
+        if (simVersion) {
+            strlcat(build, " ", oldsz);
+            strlcat(build, simVersion, oldsz);
+        }
+#endif
 }
 
+#if !TARGET_OS_DRIVERKIT
 static void
 _os_get_image_uuid(void *hdr, uuid_t uuid)
 {
@@ -97,35 +123,16 @@ _os_get_image_uuid(void *hdr, uuid_t uuid)
                uuid_clear(uuid);
        }
 }
-
-static void
-_os_abort_on_assumes_once(void)
-{
-       /* Embedded boot-args can get pretty long. Let's just hope this is big
-        * enough.
-        */
-       char bootargs[2048];
-       size_t len = sizeof(bootargs) - 1;
-
-       if (sysctlbyname("kern.bootargs", bootargs, &len, NULL, 0) == 0) {
-               if (strnstr(bootargs, "-os_assumes_fatal", len)) {
-                       _os_should_abort_on_assumes = true;
-               }
-       }
-}
+#endif
 
 static bool
 _os_abort_on_assumes(void)
 {
-       static pthread_once_t once = PTHREAD_ONCE_INIT;
        bool result = false;
 
        if (getpid() != 1) {
                if (getenv("OS_ASSUMES_FATAL")) {
                        result = true;
-               } else {
-                       pthread_once(&once, _os_abort_on_assumes_once);
-                       result = _os_should_abort_on_assumes;
                }
        } else {
                if (getenv("OS_ASSUMES_FATAL_PID1")) {
@@ -147,6 +154,7 @@ _os_find_log_redirect_func(os_mach_header *hdr)
 {
        os_redirect_t result = NULL;
 
+#if !TARGET_OS_DRIVERKIT
        char name[128];
        unsigned long size = 0;
        uint8_t *data = getsectiondata(hdr, OS_ASSUMES_REDIRECT_SEG, OS_ASSUMES_REDIRECT_SECT, &size);
@@ -161,6 +169,7 @@ _os_find_log_redirect_func(os_mach_header *hdr)
                struct _os_redirect_assumes_s *redirect = (struct _os_redirect_assumes_s *)data;
                result = redirect->redirect;
        }
+#endif
 
        return result;
 }
@@ -186,6 +195,7 @@ _os_construct_message(uint64_t code, _SIMPLE_STRING asl_message, Dl_info *info,
        uintptr_t offset = 0;
        uuid_string_t uuid_str;
 
+#if !TARGET_OS_DRIVERKIT
        void *ret = __builtin_return_address(0);
        if (dladdr(ret, info)) {
                uuid_t uuid;
@@ -196,6 +206,9 @@ _os_construct_message(uint64_t code, _SIMPLE_STRING asl_message, Dl_info *info,
                
                offset = ret - info->dli_fbase;
        }
+#else
+       info->dli_fbase = NULL;
+#endif
 
        char sig[64];
        (void)snprintf(sig, sizeof(sig), "%s:%lu", uuid_str, offset);
@@ -203,7 +216,7 @@ _os_construct_message(uint64_t code, _SIMPLE_STRING asl_message, Dl_info *info,
        char result[24];
        (void)snprintf(result, sizeof(result), "0x%llx", code);
 
-       char build[16];
+       char build[32];
        size_t bsz = sizeof(build);
        _os_get_build(build, bsz);
 
@@ -217,17 +230,63 @@ _os_construct_message(uint64_t code, _SIMPLE_STRING asl_message, Dl_info *info,
 }
 
 #pragma mark Internal Implementations
+
+os_crash_callback_t _os_crash_callback = NULL;
+
+__attribute__((always_inline))
+static inline void
+_os_crash_impl(const char *message) {
+       os_set_crash_message(message);
+#if !TARGET_OS_DRIVERKIT
+       if (!_os_crash_callback) {
+               _os_crash_callback = dlsym(RTLD_MAIN_ONLY, "os_crash_function");
+       }
+       if (_os_crash_callback) {
+               _os_crash_callback(message);
+       }
+#endif
+}
+
+#if !TARGET_OS_DRIVERKIT
+__attribute__((always_inline))
+static inline bool
+_os_crash_fmt_impl(os_log_pack_t pack, size_t pack_size)
+{
+       /*
+        * We put just the format string into the CrashReporter buffer so that we
+        * can get at least that on customer builds.
+        */
+       const char *message = pack->olp_format;
+       _os_crash_impl(message);
+
+       char *(*_os_log_pack_send_and_compose)(os_log_pack_t, os_log_t,
+                       os_log_type_t, char *, size_t) = NULL;
+       _os_log_pack_send_and_compose = dlsym(RTLD_DEFAULT, "os_log_pack_send_and_compose");
+       if (!_os_log_pack_send_and_compose) return false;
+
+       os_log_t __os_log_default = NULL;
+       __os_log_default = dlsym(RTLD_DEFAULT, "_os_log_default");
+       if (!__os_log_default) return false;
+
+       char *composed = _os_log_pack_send_and_compose(pack, __os_log_default,
+                       OS_LOG_TYPE_ERROR, NULL, 0);
+
+       abort_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT, pack, pack_size, composed, 0);
+}
+#endif
+
 __attribute__((always_inline))
 static inline void
 _os_assumes_log_impl(uint64_t code)
 {
+       char message[256] = "";
+
        _SIMPLE_STRING asl_message = _simple_asl_msg_new();
        if (asl_message) {
                Dl_info info;
-               char message[256];
                _os_construct_message(code, asl_message, &info, message, sizeof(message));
                if (!_os_log_redirect(info.dli_fbase, message)) {
-                       _os_trace_error_str(message);
+                       _os_debug_log_error_str(message);
                        _simple_asl_msg_set(asl_message, "Level", "Error");
                        _simple_asl_msg_set(asl_message, "Message", "");
                        _simple_asl_send(asl_message);
@@ -237,7 +296,7 @@ _os_assumes_log_impl(uint64_t code)
        }
 
        if (_os_abort_on_assumes()) {
-               __builtin_trap();
+               os_crash(message);
        }
 }
 
@@ -253,7 +312,7 @@ _os_assert_log_impl(uint64_t code)
                char message[256];
                _os_construct_message(code, asl_message, &info, message, sizeof(message));
                if (!_os_log_redirect(info.dli_fbase, message)) {
-                       _os_trace_error_str(message);
+                       _os_debug_log_error_str(message);
                        _simple_asl_msg_set(asl_message, "Level", "Error");
                        _simple_asl_msg_set(asl_message, "Message", "");
                        _simple_asl_send(asl_message);
@@ -263,25 +322,6 @@ _os_assert_log_impl(uint64_t code)
                result = strdup(message);
        }
 
-#if LIBC_NO_LIBCRASHREPORTERCLIENT
-       /* There is no crash report information facility on embedded, which is
-        * really regrettable. Fortunately, all we need to capture is the value
-        * which tripped up the assertion. We can just stuff that into the thread's 
-        * name.
-        */
-       char name[64];
-       (void)pthread_getname_np(pthread_self(), name, sizeof(name));
-
-       char newname[64];
-       if (strlen(name) == 0) {
-               (void)snprintf(newname, sizeof(newname), "[Fatal bug: 0x%llx]", code);
-       } else {
-               (void)snprintf(newname, sizeof(newname), "%s [Fatal bug: 0x%llx]", name, code);
-       }
-
-       (void)pthread_setname_np(newname);
-#endif
-
        return result;
 }
 
@@ -289,10 +329,11 @@ __attribute__((always_inline))
 static inline void
 _os_assumes_log_ctx_impl(os_log_callout_t callout, void *ctx, uint64_t code)
 {
+       char message[256] = "";
+
        _SIMPLE_STRING asl_message = _simple_asl_msg_new();
        if (asl_message) {
                Dl_info info;
-               char message[256];
                _os_construct_message(code, asl_message, &info, message, sizeof(message));
 
                (void)callout(asl_message, ctx, message);
@@ -300,7 +341,7 @@ _os_assumes_log_ctx_impl(os_log_callout_t callout, void *ctx, uint64_t code)
        }
 
        if (_os_abort_on_assumes()) {
-               __builtin_trap();
+               os_crash(message);
        }
 }
 
@@ -324,6 +365,18 @@ _os_assert_log_ctx_impl(os_log_callout_t callout, void *ctx, uint64_t code)
 }
 
 #pragma mark Public Interfaces
+void _os_crash(const char *message)
+{
+       _os_crash_impl(message);
+}
+
+#if !TARGET_OS_DRIVERKIT
+void _os_crash_fmt(os_log_pack_t pack, size_t pack_size)
+{
+       _os_crash_fmt_impl(pack, pack_size);
+}
+#endif
+
 void
 _os_assumes_log(uint64_t code)
 {
@@ -353,34 +406,3 @@ _os_avoid_tail_call(void)
 {
        // no-op
 }
-
-#pragma mark Legacy
-void
-_osx_assumes_log(uint64_t code)
-{
-       _os_assumes_log(code);
-}
-
-char *
-_osx_assert_log(uint64_t code)
-{
-       return _os_assert_log_impl(code);
-}
-
-void
-_osx_assumes_log_ctx(osx_log_callout_t callout, void *ctx, uint64_t code)
-{
-       _os_assumes_log_ctx_impl(callout, ctx, code);
-}
-
-char *
-_osx_assert_log_ctx(osx_log_callout_t callout, void *ctx, uint64_t code)
-{
-       return _os_assert_log_ctx_impl(callout, ctx, code);
-}
-
-void
-_osx_avoid_tail_call(void)
-{
-       _os_avoid_tail_call();
-}