]> git.saurik.com Git - apple/libc.git/blobdiff - gen/assumes.h
Libc-825.24.tar.gz
[apple/libc.git] / gen / assumes.h
index 4f266c445d5a3b81bbffbb3fc89487b495596385..70eb97d0f194d515636f53a7f663cf667ea6eb4f 100644 (file)
@@ -6,6 +6,7 @@
 __BEGIN_DECLS
 
 #include <Availability.h>
+#include <TargetConditionals.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -16,6 +17,7 @@ __BEGIN_DECLS
 #define osx_fastpath(x)        ((typeof(x))__builtin_expect((long)(x), ~0l))
 #define osx_slowpath(x)        ((typeof(x))__builtin_expect((long)(x), 0l))
 #define osx_constant(x) __builtin_constant_p((x))
+#define osx_hardware_trap() __builtin_trap()
 
 #define __OSX_COMPILETIME_ASSERT__(e) ({ \
        char __compile_time_assert__[(e) ? 1 : -1];     \
@@ -25,36 +27,201 @@ __BEGIN_DECLS
 #define osx_fastpath(x)        (x)
 #define osx_slowpath(x)        (x)
 #define osx_constant(x) ((long)0)
+#define osx_hardware_trap() abort()
 
 #define __OSX_COMPILETIME_ASSERT__(e) (e)
 #endif /* __GNUC__ */
 
+typedef bool (*osx_redirect_t)(const char *);
+
+/* The asl_message argument is an aslmsg that, when given to asl_log(), will
+ * direct the message to the MessageTracer diagnostic messages store rather than
+ * the default system log store.
+ */
+typedef bool (*osx_log_callout_t)(aslmsg asl_message, void *ctx, const char *);
+
+#if TARGET_OS_IPHONE
+#define osx_set_crash_message(arg) /* no-op */
+#else
+#include <CrashReporterClient.h>
+#define osx_set_crash_message(arg) _crc_make_setter(message, (arg))
+#endif
+
 #define osx_assumes(e) ({ \
        typeof(e) _e = osx_fastpath(e); /* Force evaluation of 'e' */ \
        if (!_e) { \
                if (osx_constant(e)) { \
                        __OSX_COMPILETIME_ASSERT__(e); \
                } \
-               _osx_assumes_log((uintptr_t)_e); \
+               _osx_assumes_log((uint64_t)(uintptr_t)_e); \
+               _osx_avoid_tail_call(); \
        } \
        _e; \
 })
 
 #define osx_assumes_zero(e) ({ \
-       typeof(e) _e = osx_slowpath(e); /* Force evaluation of 'e' */ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e) { \
+               if (osx_constant(e)) { \
+                       __OSX_COMPILETIME_ASSERT__(!e); \
+               } \
+               _osx_assumes_log((uint64_t)(uintptr_t)_e); \
+               _osx_avoid_tail_call(); \
+       } \
+       _e; \
+})
+
+/* This variant is for use with old-style POSIX APIs that return -1 on failure
+ * and set errno. If the return code is -1, the value logged will be as though
+ * osx_assumes_zero(errno) was used. It encapsulates the following pattern:
+ *
+ * int tubes[2];
+ * if (pipe(tubes) == -1) {
+ *     (void)osx_assumes_zero(errno);
+ * }
+ */
+#define posix_assumes_zero(e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e == (typeof(e))-1) { \
+               _osx_assumes_log((uint64_t)(uintptr_t)errno); \
+               _osx_avoid_tail_call(); \
+       } \
+       _e; \
+})
+
+#define osx_assert(e) ({ \
+       typeof(e) _e = osx_fastpath(e); \
+       if (!_e) { \
+               if (osx_constant(e)) { \
+                       __OSX_COMPILETIME_ASSERT__(e); \
+               } \
+\
+               char *message = _osx_assert_log((uint64_t)(uintptr_t)_e); \
+               osx_set_crash_message(message); \
+               osx_hardware_trap(); \
+               free(message); \
+       } \
+})
+
+#define osx_assert_zero(e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e) { \
+               if (osx_constant(e)) { \
+                       __OSX_COMPILETIME_ASSERT__(!e); \
+               } \
+\
+               char *message = _osx_assert_log((uint64_t)(uintptr_t)_e); \
+               osx_set_crash_message(message); \
+               osx_hardware_trap(); \
+               free(message); \
+       } \
+})
+
+#define posix_assert_zero(e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e == (typeof(e))-1) { \
+               char *message = _osx_assert_log((uint64_t)(uintptr_t)errno); \
+               osx_set_crash_message(message); \
+               osx_hardware_trap(); \
+               free(message); \
+       } \
+})
+
+/* These are for defining your own assumes()-like wrapper calls so that you can
+ * log additional information, such as the about-PID, sender, etc. They're
+ * generally not useful for direct inclusion in your code.
+ */
+#define osx_assumes_ctx(f, ctx, e) ({ \
+       typeof(e) _e = osx_fastpath(e); \
+       if (!_e) { \
+               if (osx_constant(e)) { \
+                       __OSX_COMPILETIME_ASSERT__(e); \
+               } \
+               _osx_assumes_log_ctx(f, ctx, (uintptr_t)_e); \
+               _osx_avoid_tail_call(); \
+       } \
+       _e; \
+})
+
+#define osx_assumes_zero_ctx(f, ctx, e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
        if (_e) { \
                if (osx_constant(e)) { \
                        __OSX_COMPILETIME_ASSERT__(!e); \
                } \
-               _osx_assumes_log((uintptr_t)_e); \
+               _osx_assumes_log_ctx((f), (ctx), (uintptr_t)_e); \
+               _osx_avoid_tail_call(); \
        } \
        _e; \
 })
 
+#define posix_assumes_zero_ctx(f, ctx, e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e == (typeof(e))-1) { \
+               _osx_assumes_log_ctx((f), (ctx), (uintptr_t)errno); \
+               _osx_avoid_tail_call(); \
+       } \
+       _e; \
+})
+
+#define osx_assert_ctx(f, ctx, e) ({ \
+       typeof(e) _e = osx_fastpath(e); \
+       if (!_e) { \
+               if (osx_constant(e)) { \
+                       __OSX_COMPILETIME_ASSERT__(e); \
+               } \
+\
+               char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)_e); \
+               osx_set_crash_message(message); \
+               osx_hardware_trap(); \
+               free(message); \
+       } \
+})
+
+#define osx_assert_zero_ctx(f, ctx, e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e) { \
+               if (osx_constant(e)) { \
+                       __OSX_COMPILETIME_ASSERT__(!e); \
+               } \
+\
+               char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)_e); \
+               osx_set_crash_message(message); \
+               osx_hardware_trap(); \
+               free(message); \
+       } \
+})
+
+#define posix_assert_zero_ctx(f, ctx, e) ({ \
+       typeof(e) _e = osx_slowpath(e); \
+       if (_e == (typeof(e))-1) { \
+               char *message = _osx_assert_log_ctx((f), (ctx), (uint64_t)(uintptr_t)errno); \
+               osx_set_crash_message(message); \
+               osx_hardware_trap(); \
+               free(message); \
+       } \
+})
+
 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
 extern void
 _osx_assumes_log(uint64_t code);
 
+__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
+extern char *
+_osx_assert_log(uint64_t code);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
+extern void
+_osx_assumes_log_ctx(osx_log_callout_t callout, void *ctx, uint64_t code);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
+extern char *
+_osx_assert_log_ctx(osx_log_callout_t callout, void *ctx, uint64_t code);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0)
+extern void
+_osx_avoid_tail_call(void);
+
 __END_DECLS
 
 #endif /* __OSX_ASSUMES_H__ */