···11+/*
22+ * Copyright (c) 2013-2016 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_APACHE_LICENSE_HEADER_START@
55+ *
66+ * Licensed under the Apache License, Version 2.0 (the "License");
77+ * you may not use this file except in compliance with the License.
88+ * You may obtain a copy of the License at
99+ *
1010+ * http://www.apache.org/licenses/LICENSE-2.0
1111+ *
1212+ * Unless required by applicable law or agreed to in writing, software
1313+ * distributed under the License is distributed on an "AS IS" BASIS,
1414+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515+ * See the License for the specific language governing permissions and
1616+ * limitations under the License.
1717+ *
1818+ * @APPLE_APACHE_LICENSE_HEADER_END@
1919+ */
2020+2121+#ifndef __FIREHOSE_ACTIVITY__
2222+#define __FIREHOSE_ACTIVITY__
2323+2424+#include <machine/cpu_capabilities.h>
2525+#include <mach/mach_time.h>
2626+#include <os/base.h>
2727+#if KERNEL
2828+#include <atm/atm_internal.h>
2929+#endif
3030+#include "firehose_types_private.h"
3131+3232+OS_ASSUME_NONNULL_BEGIN
3333+3434+/*!
3535+ * @typedef firehose_tracepoint_id_u
3636+ *
3737+ * @abstract
3838+ * Broken down tracepoint identifier.
3939+ */
4040+typedef union {
4141+ struct {
4242+ firehose_tracepoint_namespace_t _namespace;
4343+ firehose_tracepoint_type_t _type;
4444+ firehose_tracepoint_flags_t _flags;
4545+ uint32_t _code;
4646+ } ftid;
4747+ firehose_tracepoint_id_t ftid_value;
4848+} firehose_tracepoint_id_u;
4949+5050+#define FIREHOSE_STAMP_SLOP (1ULL << 36) // ~1minute
5151+5252+/*!
5353+ * @typedef firehose_trace_uuid_info_t
5454+ *
5555+ * @abstract
5656+ * Info needed by logd when kexts are loaded or unloaded
5757+ *
5858+ */
5959+typedef struct firehose_trace_uuid_info_s {
6060+ uuid_t ftui_uuid; /* uuid of binary */
6161+ uint64_t ftui_address; /* load address */
6262+ uint64_t ftui_size; /* load size */
6363+ char ftui_path[]; /* full path of binary - Unused in the kernel*/
6464+} *firehose_trace_uuid_info_t;
6565+6666+/*!
6767+ * @typedef firehose_tracepoint_t
6868+ */
6969+typedef struct firehose_tracepoint_s {
7070+ firehose_tracepoint_id_u ft_id;
7171+ uint64_t ft_thread;
7272+ union {
7373+ struct {
7474+ uint64_t ft_timestamp_delta : 48;
7575+ uint64_t ft_length : 16;
7676+ };
7777+ uint64_t ft_stamp_and_length;
7878+ };
7979+ uint8_t ft_data[];
8080+} *firehose_tracepoint_t;
8181+8282+#define FIREHOSE_TRACE_ID_MAKE(ns, type, flags, code) \
8383+ (((firehose_tracepoint_id_u){ .ftid = { \
8484+ ._namespace = ns, \
8585+ ._type = type, \
8686+ ._flags = flags, \
8787+ ._code = code, \
8888+ } }).ftid_value)
8989+9090+#define FIREHOSE_TRACE_ID_SET_NS(tid, ns) \
9191+ ((tid).ftid._namespace = firehose_tracepoint_namespace_##ns)
9292+9393+#define FIREHOSE_TRACE_ID_SET_TYPE(tid, ns, type) \
9494+ ((tid).ftid._type = _firehose_tracepoint_type_##ns##_##type)
9595+9696+#define FIREHOSE_TRACE_ID_HAS_FLAG(tid, ns, flag) \
9797+ ((tid).ftid._flags & _firehose_tracepoint_flags_##ns##_##flag)
9898+#define FIREHOSE_TRACE_ID_SET_FLAG(tid, ns, flag) \
9999+ ((void)((tid).ftid._flags |= _firehose_tracepoint_flags_##ns##_##flag))
100100+#define FIREHOSE_TRACE_ID_CLEAR_FLAG(tid, ns, flag) \
101101+ ((void)((tid).ftid._flags &= ~_firehose_tracepoint_flags_##ns##_##flag))
102102+103103+#define FIREHOSE_TRACE_ID_SET_CODE(tid, code) \
104104+ ((tid).ftid._code = code)
105105+106106+__BEGIN_DECLS
107107+108108+#if __has_feature(address_sanitizer)
109109+__attribute__((no_sanitize("address")))
110110+#endif
111111+__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0)
112112+__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
113113+OS_ALWAYS_INLINE
114114+static inline bool
115115+firehose_precise_timestamps_enabled(void)
116116+{
117117+#if KERNEL
118118+ return (atm_get_diagnostic_config() & 0x80) == 0;
119119+#else
120120+ return (*((volatile uint32_t *)_COMM_PAGE_ATM_DIAGNOSTIC_CONFIG) & 0x80) == 0;
121121+#endif
122122+}
123123+124124+#if __has_feature(address_sanitizer)
125125+__attribute__((no_sanitize("address")))
126126+#endif
127127+__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0)
128128+__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
129129+OS_ALWAYS_INLINE
130130+static inline uint64_t
131131+firehose_tracepoint_time(firehose_activity_flags_t flags)
132132+{
133133+ if (firehose_precise_timestamps_enabled() ||
134134+ (flags & firehose_activity_flags_precise_timestamp)) {
135135+ return mach_continuous_time();
136136+ } else {
137137+ return mach_continuous_approximate_time();
138138+ }
139139+}
140140+141141+#ifdef KERNEL
142142+__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0)
143143+__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
144144+void
145145+firehose_trace_metadata(firehose_stream_t stream, firehose_tracepoint_id_u ftid,
146146+ uint64_t stamp, const void* pubdata, size_t publen);
147147+#endif
148148+__END_DECLS
149149+150150+OS_ASSUME_NONNULL_END
151151+152152+#endif // __FIREHOSE_FIREHOSE__
+501
src/duct/include/os/log.h
···11+/*
22+ * Copyright (c) 2015 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#ifndef __os_log_h
2525+#define __os_log_h
2626+2727+#include <os/object.h>
2828+#include <stdint.h>
2929+#include <stdbool.h>
3030+3131+#ifndef __has_attribute
3232+#define __has_attribute(x) 0
3333+#endif
3434+3535+#ifndef __has_builtin
3636+#define __has_builtin(x) 0
3737+#endif
3838+3939+#if __has_attribute(not_tail_called)
4040+#define OS_LOG_NOTAILCALL __attribute__((not_tail_called))
4141+#define OS_LOG_NOTAILCALL_MARKER
4242+#else
4343+#define OS_LOG_NOTAILCALL
4444+#define OS_LOG_NOTAILCALL_MARKER __asm__("")
4545+#endif
4646+4747+__BEGIN_DECLS
4848+4949+extern void *__dso_handle;
5050+5151+OS_ALWAYS_INLINE static inline void _os_log_verify_format_str(__unused const char *msg, ...) __attribute__((format(os_trace, 1, 2)));
5252+OS_ALWAYS_INLINE static inline void _os_log_verify_format_str(__unused const char *msg, ...) { /* placeholder */ }
5353+5454+#if OS_OBJECT_USE_OBJC
5555+OS_OBJECT_DECL(os_log);
5656+#else
5757+typedef struct os_log_s *os_log_t;
5858+#endif /* OS_OBJECT_USE_OBJC */
5959+6060+/*!
6161+ * @const OS_LOG_DISABLED
6262+ *
6363+ * @discussion
6464+ * Use this to disable a specific log message.
6565+ */
6666+#define OS_LOG_DISABLED NULL
6767+6868+/*!
6969+ * @const OS_LOG_DEFAULT
7070+ *
7171+ * @discussion
7272+ * Use this to log a message in accordance with current system settings.
7373+ */
7474+#define OS_LOG_DEFAULT OS_OBJECT_GLOBAL_OBJECT(os_log_t, _os_log_default)
7575+__OSX_AVAILABLE_STARTING(__MAC_10_12,__IPHONE_10_0)
7676+OS_EXPORT
7777+struct os_log_s _os_log_default;
7878+7979+/*!
8080+ * @enum os_log_type_t
8181+ *
8282+ * @discussion
8383+ * Supported log message types.
8484+ *
8585+ * @constant OS_LOG_TYPE_DEFAULT
8686+ * Equivalent type for "os_log()" messages, i.e., default messages that are always
8787+ * captured to memory or disk.
8888+ *
8989+ * @constant OS_LOG_TYPE_INFO
9090+ * Equivalent type for "os_log_info()" messages, i.e., Additional informational messages.
9191+ *
9292+ * @constant OS_LOG_TYPE_DEBUG
9393+ * Equivalent type for "os_log_debug()" messages, i.e., Debug messages.
9494+ *
9595+ * @constant OS_LOG_TYPE_ERROR
9696+ * Equivalent type for "os_log_error()" messages, i.e., local process error messages.
9797+ *
9898+ * @constant OS_LOG_TYPE_FAULT
9999+ * Equivalent type for "os_log_fault()" messages, i.e., a system error that involves
100100+ * potentially more than one process, usually used by daemons and services.
101101+ */
102102+OS_ENUM(os_log_type, uint8_t,
103103+ OS_LOG_TYPE_DEFAULT = 0x00,
104104+ OS_LOG_TYPE_INFO = 0x01,
105105+ OS_LOG_TYPE_DEBUG = 0x02,
106106+ OS_LOG_TYPE_ERROR = 0x10,
107107+ OS_LOG_TYPE_FAULT = 0x11);
108108+109109+/*!
110110+ * @function os_log_create
111111+ *
112112+ * @abstract
113113+ * Creates a log object to be used with other log related functions.
114114+ *
115115+ * @discussion
116116+ * Creates a log object to be used with other log related functions. The
117117+ * log object serves two purposes: (1) tag related messages by subsystem
118118+ * and category name for easy filtering, and (2) control logging system
119119+ * behavior for messages.
120120+ *
121121+ * A log object may customize logging system behavior for its messages by
122122+ * adding a configuration file in /Library/LogPreferences. Most options
123123+ * accept 3 values: "Default", "Yes" or "No" as strings, where "Default"
124124+ * signifies follow system behavior for the level of messages.
125125+ *
126126+ * For log:
127127+ *
128128+ * os_log_create("com.company.mysubsystem", "connections");
129129+ *
130130+ * System-provided preferences are located in /System/Library/LogPreferences/<subsystem>.plist
131131+ *
132132+ * <dict>
133133+ *
134134+ * <!-- Default options applied to message types in each category, which can be overriden. -->
135135+ * <key>DEFAULT-OPTIONS</key>
136136+ * <dict>
137137+ * <key>Enabled</key> <!-- Enabled state follows system defaults -->
138138+ * <string>Default</string>
139139+ * <key>Persist</key> <!-- Do not persist to disk, use memory-only buffer if enabled -->
140140+ * <string>No</string>
141141+ * <key>TTL</key> <!-- Follow system default behavior if persistence is enabled -->
142142+ * <string>Default</string> <!-- Can specify in days with "d" or hours "h" (e.g., "4h" = 4 hours) -->
143143+ * </dict>
144144+ *
145145+ * <!-- category named “connections” -->
146146+ * <key>connections</key>
147147+ * <dict>
148148+ *
149149+ * <!-- Options that control "os_log()" behavior. The "Enabled" option is ignored. -->
150150+ * <key>Default</key>
151151+ * <dict>
152152+ * <key>Persist</key> <!-- Always persist to disk -->
153153+ * <string>Yes</string>
154154+ * <key>TTL</key> <!-- Store default messages for maximum 4 days -->
155155+ * <integer>4d</integer>
156156+ * </dict>
157157+ *
158158+ * <!-- Subdictionary of options that control "os_log_info()" behavior -->
159159+ * <key>Info</key>
160160+ * <dict>
161161+ * <key>Persist</key> <!-- If enabled persist to disk -->
162162+ * <string>Yes</string>
163163+ * <key>TTL</key> <!-- Store Info messages for 2 days -->
164164+ * <string>2d</string>
165165+ * </dict>
166166+ *
167167+ * <!-- Subdictionary of options that control "os_log_debug()" behavior -->
168168+ * <key>Debug</key>
169169+ * <dict>
170170+ * <key>Enabled</key> <!-- Not enabled, must be enabled specifically -->
171171+ * <string>No</string>
172172+ * </dict>
173173+ * </dict>
174174+ * </dict>
175175+ *
176176+ * All other preferences and system-overrides are stored in /Library/LogPreferences/.
177177+ *
178178+ * @param subsystem
179179+ * The identifier of the given subsystem should be in reverse DNS form
180180+ * (i.e., com.company.mysubsystem). This string must be a constant string,
181181+ * not dynamically generated.
182182+ *
183183+ * @param category
184184+ * The category within the given subsystem that specifies the settings for
185185+ * the log object. This string must be a constant string, not dynamically
186186+ * generated.
187187+ *
188188+ * @result
189189+ * Returns an os_log_t value to be passed to other os_log API calls. This
190190+ * should be called once at log initialization and rely on system to detect
191191+ * changes to settings. This object should be released when no longer used
192192+ * via os_release or -[release] method.
193193+ *
194194+ * A value will always be returned to allow for dynamic enablement.
195195+ */
196196+__OSX_AVAILABLE_STARTING(__MAC_10_12,__IPHONE_10_0)
197197+OS_EXPORT OS_NOTHROW OS_WARN_RESULT OS_OBJECT_RETURNS_RETAINED
198198+os_log_t
199199+os_log_create(const char *subsystem, const char *category);
200200+201201+/*!
202202+ * @function os_log_info_enabled
203203+ *
204204+ * @abstract
205205+ * Returns if development log messages are enabled for a particular log object.
206206+ *
207207+ * @discussion
208208+ * Returns if development log messages are enabled for a particular log object.
209209+ *
210210+ * @param log
211211+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
212212+ *
213213+ * @result
214214+ * Returns ‘true’ if debug log messages are enabled.
215215+ */
216216+__WATCHOS_AVAILABLE(3.0) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0)
217217+OS_EXPORT OS_NOTHROW OS_WARN_RESULT
218218+bool
219219+os_log_info_enabled(os_log_t log);
220220+221221+/*!
222222+ * @function os_log_debug_enabled
223223+ *
224224+ * @abstract
225225+ * Returns if debug log messages are enabled for a particular log object.
226226+ *
227227+ * @discussion
228228+ * Returns if debug log messages are enabled for a particular log object.
229229+ *
230230+ * @param log
231231+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
232232+ *
233233+ * @result
234234+ * Returns ‘true’ if debug log messages are enabled.
235235+ */
236236+__WATCHOS_AVAILABLE(3.0) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0)
237237+OS_EXPORT OS_NOTHROW OS_WARN_RESULT
238238+bool
239239+os_log_debug_enabled(os_log_t log);
240240+241241+/*!
242242+ * @function os_log
243243+ *
244244+ * @abstract
245245+ * Insert a log message into the Unified Logging and Tracing system.
246246+ *
247247+ * @discussion
248248+ * Insert a log message into the Unified Logging and Tracing system in
249249+ * accordance with the preferences specified by the provided log object.
250250+ * These messages cannot be disabled and therefore always captured either
251251+ * to memory or disk.
252252+ *
253253+ * When an os_activity_id_t is present, the log message will also be scoped by
254254+ * that identifier. Activities provide granular filtering of log messages
255255+ * across threads and processes.
256256+ *
257257+ * There is a physical cap of 256 bytes per entry for dynamic content,
258258+ * i.e., %s and %@, that can be written to the persistence store. As such,
259259+ * all content exceeding the limit will be truncated before written to disk.
260260+ * Live streams will continue to show the full content.
261261+ *
262262+ * @param log
263263+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
264264+ *
265265+ * @param format
266266+ * A format string to generate a human-readable log message when the log
267267+ * line is decoded. This string must be a constant string, not dynamically
268268+ * generated. Supports all standard printf types and %@ (objects).
269269+ */
270270+#define os_log(log, format, ...) __extension__({ \
271271+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
272272+ __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
273273+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
274274+ _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_DEFAULT, _os_log_fmt, ##__VA_ARGS__); \
275275+ __asm__(""); /* avoid tailcall */ \
276276+})
277277+278278+/*!
279279+ * @function os_log_info
280280+ *
281281+ * @abstract
282282+ * Insert a development log message into the Unified Logging and Tracing system.
283283+ *
284284+ * @discussion
285285+ * Insert a log message into the Unified Logging and Tracing system in
286286+ * accordance with the preferences specified by the provided log object.
287287+ *
288288+ * When an os_activity_id_t is present, the log message will also be scoped by
289289+ * that identifier. Activities provide granular filtering of log messages
290290+ * across threads and processes.
291291+ *
292292+ * There is a physical cap of 256 bytes per entry for dynamic content,
293293+ * i.e., %s and %@, that can be written to the persistence store. As such,
294294+ * all content exceeding the limit will be truncated before written to disk.
295295+ * Live streams will continue to show the full content.
296296+ *
297297+ * @param log
298298+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
299299+ *
300300+ * @param format
301301+ * A format string to generate a human-readable log message when the log
302302+ * line is decoded. This string must be a constant string, not dynamically
303303+ * generated. Supports all standard printf types and %@ (objects).
304304+ */
305305+#define os_log_info(log, format, ...) __extension__({ \
306306+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
307307+ __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
308308+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
309309+ _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_INFO, _os_log_fmt, ##__VA_ARGS__); \
310310+ __asm__(""); /* avoid tailcall */ \
311311+})
312312+313313+/*!
314314+ * @function os_log_debug
315315+ *
316316+ * @abstract
317317+ * Insert a debug log message into the Unified Logging and Tracing system.
318318+ *
319319+ * @discussion
320320+ * Insert a debug log message into the Unified Logging and Tracing system in
321321+ * accordance with the preferences specified by the provided log object.
322322+ *
323323+ * When an os_activity_id_t is present, the log message will also be scoped by
324324+ * that identifier. Activities provide granular filtering of log messages
325325+ * across threads and processes.
326326+ *
327327+ * There is a physical cap of 256 bytes per entry for dynamic content,
328328+ * i.e., %s and %@, that can be written to the persistence store. As such,
329329+ * all content exceeding the limit will be truncated before written to disk.
330330+ * Live streams will continue to show the full content.
331331+ *
332332+ * @param log
333333+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
334334+ *
335335+ * @param format
336336+ * A format string to generate a human-readable log message when the log
337337+ * line is decoded. This string must be a constant string, not dynamically
338338+ * generated. Supports all standard printf types and %@ (objects).
339339+ */
340340+#define os_log_debug(log, format, ...) __extension__({ \
341341+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
342342+ __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
343343+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
344344+ _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_DEBUG, _os_log_fmt, ##__VA_ARGS__); \
345345+ __asm__(""); /* avoid tailcall */ \
346346+})
347347+348348+/*!
349349+ * @function os_log_error
350350+ *
351351+ * @abstract
352352+ * Insert an error log message into the Unified Logging and Tracing system.
353353+ *
354354+ * @discussion
355355+ * Insert an error log message into the Unified Logging and Tracing system.
356356+ *
357357+ * When an os_activity_id_t is present, the log message will also be scoped by
358358+ * that identifier. Activities provide granular filtering of log messages
359359+ * across threads and processes.
360360+ *
361361+ * There is a physical cap of 256 bytes per entry for dynamic content,
362362+ * i.e., %s and %@, that can be written to the persistence store. As such,
363363+ * all content exceeding the limit will be truncated before written to disk.
364364+ * Live streams will continue to show the full content.
365365+ *
366366+ * @param log
367367+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
368368+ *
369369+ * @param format
370370+ * A format string to generate a human-readable log message when the log
371371+ * line is decoded. This string must be a constant string, not dynamically
372372+ * generated. Supports all standard printf types and %@ (objects).
373373+ */
374374+#define os_log_error(log, format, ...) __extension__({ \
375375+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
376376+ __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
377377+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
378378+ _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_ERROR, _os_log_fmt, ##__VA_ARGS__); \
379379+ __asm__(""); /* avoid tailcall */ \
380380+})
381381+382382+/*!
383383+ * @function os_log_fault
384384+ *
385385+ * @abstract
386386+ * Insert a fault log message into the Unified Logging and Tracing system.
387387+ *
388388+ * @discussion
389389+ * Log a fault message issue into the Unified Logging and Tracing system
390390+ * signifying a multi-process (i.e., system error) related issue, either
391391+ * due to interaction via IPC or some other. Faults will gather information
392392+ * from the entire process chain and record it for later inspection.
393393+ *
394394+ * When an os_activity_id_t is present, the log message will also be scoped by
395395+ * that identifier. Activities provide granular filtering of log messages
396396+ * across threads and processes.
397397+ *
398398+ * There is a physical cap of 256 bytes per entry for dynamic content,
399399+ * i.e., %s and %@, that can be written to the persistence store. As such,
400400+ * all content exceeding the limit will be truncated before written to disk.
401401+ * Live streams will continue to show the full content.
402402+ *
403403+ * @param log
404404+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
405405+ *
406406+ * @param format
407407+ * A format string to generate a human-readable log message when the log
408408+ * line is decoded. This string must be a constant string, not dynamically
409409+ * generated. Supports all standard printf types and %@ (objects).
410410+ */
411411+#define os_log_fault(log, format, ...) __extension__({ \
412412+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
413413+ __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
414414+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
415415+ _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_FAULT, _os_log_fmt, ##__VA_ARGS__); \
416416+ __asm__(""); /* avoid tailcall */ \
417417+})
418418+419419+/*!
420420+ * @function os_log_with_type
421421+ *
422422+ * @abstract
423423+ * Log a message using a specific type.
424424+ *
425425+ * @discussion
426426+ * Will log a message with the provided os_log_type_t.
427427+ *
428428+ * @param log
429429+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
430430+ *
431431+ * @param type
432432+ * Pass a valid type from os_log_type_t.
433433+ *
434434+ * @param format
435435+ * A format string to generate a human-readable log message when the log
436436+ * line is decoded. This string must be a constant string, not dynamically
437437+ * generated. Supports all standard printf types and %@ (objects).
438438+ */
439439+#define os_log_with_type(log, type, format, ...) __extension__({ \
440440+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
441441+ __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
442442+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
443443+ _os_log_internal(&__dso_handle, log, type, _os_log_fmt, ##__VA_ARGS__); \
444444+ __asm__(""); /* avoid tailcall */ \
445445+})
446446+447447+/*!
448448+ * @function os_log_sensitive_debug
449449+ *
450450+ * @abstract
451451+ * Insert a debug log message containing sensitive content (i.e., personal
452452+ * identifying information).
453453+ *
454454+ * @discussion
455455+ * Insert a debug log message containing sensitive content (i.e., personal
456456+ * identifying information) in accordance with the preferences specified by
457457+ * the provided log object.
458458+ *
459459+ * All strings are considered potentially sensitive, though this call
460460+ * specifically signifies the message as containing sensitive content.
461461+ * The message will be stored separately from other messages.
462462+ *
463463+ * When an os_activity_id_t is present, the log message will also be scoped by
464464+ * that identifier. Activities provide granular filtering of log messages
465465+ * across threads and processes.
466466+ *
467467+ * There is a physical cap of 256 bytes per entry for dynamic content,
468468+ * i.e., %s and %@, that can be written to the persistence store. As such,
469469+ * all content exceeding the limit will be truncated before written to disk.
470470+ * Live streams will continue to show the full content.
471471+ *
472472+ * @param log
473473+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
474474+ *
475475+ * @param format
476476+ * A format string to generate a human-readable log message when the log
477477+ * line is decoded. This string must be a constant string, not dynamically
478478+ * generated. Supports all standard printf types and %@ (objects).
479479+ */
480480+#define os_log_sensitive_debug(log, format, ...) __extension__({ \
481481+ _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
482482+ __attribute__((section("__TEXT,__os_log_sens"))) static const char _os_log_fmt[] = format; \
483483+ _os_log_verify_format_str(format, ##__VA_ARGS__); \
484484+ _os_log_sensitive(&__dso_handle, log, OS_LOG_TYPE_DEBUG, _os_log_fmt, ##__VA_ARGS__); \
485485+ __asm__(""); /* avoid tailcall */ \
486486+})
487487+488488+/*!
489489+ * @function _os_log_internal
490490+ *
491491+ * @abstract
492492+ * Internal function used by macros.
493493+ */
494494+__WATCHOS_AVAILABLE(3.0) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0)
495495+OS_EXPORT OS_NOTHROW
496496+void
497497+_os_log_internal(void *dso, os_log_t log, os_log_type_t type, const char *message, ...);
498498+499499+__END_DECLS
500500+501501+#endif /* __os_log_h */
+94
src/duct/include/os/log_private.h
···11+/*
22+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#ifndef __os_log_private_h
2525+#define __os_log_private_h
2626+2727+#include <os/log.h>
2828+#include <firehose/tracepoint_private.h>
2929+#include <sys/queue.h>
3030+3131+__BEGIN_DECLS
3232+3333+/*!
3434+ * @function os_log_with_args
3535+ *
3636+ * @abstract
3737+ * os_log variant that supports va_list args.
3838+ *
3939+ * @discussion
4040+ * os_log variant that supports va_list args. This SPI should only be used
4141+ * to shim legacy logging systems through os_log.
4242+ *
4343+ * @param oslog
4444+ * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
4545+ *
4646+ * @param type
4747+ * Pass one of the following message types.
4848+ * OS_LOG_TYPE_DEFAULT
4949+ * OS_LOG_TYPE_DEBUG
5050+ * OS_LOG_TYPE_INFO
5151+ * OS_LOG_TYPE_ERROR
5252+ * OS_LOG_TYPE_FAULT
5353+ *
5454+ * @param format
5555+ * A format string to generate a human-readable log message when the log
5656+ * line is decoded. Supports all standard printf types in addition to %@
5757+ * and %m (objects and errno respectively).
5858+ *
5959+ * @param args
6060+ * A va_list containing the values for the format string.
6161+ *
6262+ * @param ret_addr
6363+ * Pass the __builtin_return_address(0) of the function that created the
6464+ * va_list from variadic arguments. The caller must be the same binary
6565+ * that generated the message and provided the format string.
6666+ */
6767+__OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0)
6868+OS_EXPORT OS_NOTHROW OS_LOG_NOTAILCALL
6969+void
7070+os_log_with_args(os_log_t oslog, os_log_type_t type, const char *format, va_list args, void *ret_addr);
7171+7272+/*!
7373+ * @enum oslog_stream_link_type_t
7474+ */
7575+OS_ENUM(oslog_stream_link_type, uint8_t,
7676+ oslog_stream_link_type_log = 0x0,
7777+ oslog_stream_link_type_metadata = 0x1,
7878+);
7979+8080+/*!
8181+ * @typedef oslog_stream_buf_entry_t
8282+ */
8383+typedef struct oslog_stream_buf_entry_s {
8484+ STAILQ_ENTRY(oslog_stream_buf_entry_s) buf_entries;
8585+ uint64_t timestamp;
8686+ int offset;
8787+ uint16_t size;
8888+ oslog_stream_link_type_t type;
8989+ struct firehose_tracepoint_s metadata[];
9090+} *oslog_stream_buf_entry_t;
9191+9292+__END_DECLS
9393+9494+#endif // __os_log_private_h
+893
src/duct/include/os/trace.h
···11+/*
22+ * Copyright (c) 2013-2015 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#ifndef __OS_TRACE_H__
2525+#define __OS_TRACE_H__
2626+2727+#include <Availability.h>
2828+#include <os/base.h>
2929+#include <sys/types.h>
3030+#include <stdint.h>
3131+#include <stdbool.h>
3232+#include <stdarg.h>
3333+#if __has_include(<xpc/xpc.h>)
3434+#include <xpc/xpc.h>
3535+#else
3636+typedef void *xpc_object_t;
3737+#endif
3838+3939+#if !__GNUC__
4040+#error "must be GNU C compatible"
4141+#endif
4242+4343+__BEGIN_DECLS
4444+4545+extern void *__dso_handle;
4646+4747+OS_ALWAYS_INLINE
4848+static inline void
4949+_os_trace_verify_printf(const char *msg, ...) __attribute__((format(printf, 1, 2)))
5050+{
5151+#pragma unused(msg)
5252+}
5353+5454+#if !defined OS_COUNT_ARGS
5555+#define OS_COUNT_ARGS(...) OS_COUNT_ARGS1(, ##__VA_ARGS__, _8, _7, _6, _5, _4, _3, _2, _1, _0)
5656+#define OS_COUNT_ARGS1(z, a, b, c, d, e, f, g, h, cnt, ...) cnt
5757+#endif
5858+5959+/* use old macros for anything less than iOS 10 and MacOS 10.12 */
6060+#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0) \
6161+ || (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_3_0) \
6262+ || (defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < __TVOS_10_0) \
6363+ || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12)
6464+6565+#define _os_trace_0(_l, _m, _t) __extension__({ \
6666+ _os_trace_verify_printf(_l); \
6767+ _os_trace_with_buffer(&__dso_handle, _m, _t, NULL, 0, NULL); \
6868+ __asm__(""); /* avoid tailcall */ \
6969+})
7070+7171+#define _os_trace_1(_l, _m, _t, _1) __extension__({ \
7272+ _Pragma("clang diagnostic push") \
7373+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
7474+ const __typeof__(_1) _c1 = _1; \
7575+ _os_trace_verify_printf(_l, _c1); \
7676+ const struct __attribute__((packed)) { \
7777+ __typeof__(_c1) _f1; \
7878+ uint8_t _s[1]; \
7979+ uint8_t _cnt; \
8080+ } _buf = { \
8181+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
8282+ ._cnt = 1, \
8383+ }; \
8484+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
8585+ __asm__(""); /* avoid tailcall */ \
8686+ _Pragma("clang diagnostic pop") \
8787+})
8888+8989+#define _os_trace_2(_l, _m, _t, _1, _2) __extension__({ \
9090+ _Pragma("clang diagnostic push") \
9191+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
9292+ const __typeof__(_1) _c1 = _1; \
9393+ const __typeof__(_2) _c2 = _2; \
9494+ _os_trace_verify_printf(_l, _c1, _c2); \
9595+ const struct __attribute__((packed)) { \
9696+ __typeof__(_c1) _f1; \
9797+ __typeof__(_c2) _f2; \
9898+ uint8_t _s[2]; \
9999+ uint8_t _cnt; \
100100+ } _buf = { \
101101+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
102102+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
103103+ ._cnt = 2, \
104104+ }; \
105105+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
106106+ __asm__(""); /* avoid tailcall */ \
107107+ _Pragma("clang diagnostic pop") \
108108+})
109109+110110+#define _os_trace_3(_l, _m, _t, _1, _2, _3) __extension__({ \
111111+ _Pragma("clang diagnostic push") \
112112+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
113113+ const __typeof__(_1) _c1 = _1; \
114114+ const __typeof__(_2) _c2 = _2; \
115115+ const __typeof__(_3) _c3 = _3; \
116116+ _os_trace_verify_printf(_l, _c1, _c2, _c3); \
117117+ const struct __attribute__((packed)) { \
118118+ __typeof__(_c1) _f1; \
119119+ __typeof__(_c2) _f2; \
120120+ __typeof__(_c3) _f3; \
121121+ uint8_t _s[3]; \
122122+ uint8_t _cnt; \
123123+ } _buf = { \
124124+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
125125+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
126126+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
127127+ ._cnt = 3, \
128128+ }; \
129129+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
130130+ __asm__(""); /* avoid tailcall */ \
131131+ _Pragma("clang diagnostic pop") \
132132+})
133133+134134+#define _os_trace_4(_l, _m, _t, _1, _2, _3, _4) __extension__({ \
135135+ _Pragma("clang diagnostic push") \
136136+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
137137+ const __typeof__(_1) _c1 = _1; \
138138+ const __typeof__(_2) _c2 = _2; \
139139+ const __typeof__(_3) _c3 = _3; \
140140+ const __typeof__(_4) _c4 = _4; \
141141+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4); \
142142+ const struct __attribute__((packed)) { \
143143+ __typeof__(_c1) _f1; \
144144+ __typeof__(_c2) _f2; \
145145+ __typeof__(_c3) _f3; \
146146+ __typeof__(_c4) _f4; \
147147+ uint8_t _s[4]; \
148148+ uint8_t _cnt; \
149149+ } _buf = { \
150150+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
151151+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
152152+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
153153+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
154154+ ._cnt = 4, \
155155+ }; \
156156+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
157157+ __asm__(""); /* avoid tailcall */ \
158158+ _Pragma("clang diagnostic pop") \
159159+})
160160+161161+#define _os_trace_5(_l, _m, _t, _1, _2, _3, _4, _5) __extension__({ \
162162+ _Pragma("clang diagnostic push") \
163163+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
164164+ const __typeof__(_1) _c1 = _1; \
165165+ const __typeof__(_2) _c2 = _2; \
166166+ const __typeof__(_3) _c3 = _3; \
167167+ const __typeof__(_4) _c4 = _4; \
168168+ const __typeof__(_5) _c5 = _5; \
169169+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5); \
170170+ const struct __attribute__((packed)) { \
171171+ __typeof__(_c1) _f1; \
172172+ __typeof__(_c2) _f2; \
173173+ __typeof__(_c3) _f3; \
174174+ __typeof__(_c4) _f4; \
175175+ __typeof__(_c5) _f5; \
176176+ uint8_t _s[5]; \
177177+ uint8_t _cnt; \
178178+ } _buf = { \
179179+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
180180+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
181181+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
182182+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
183183+ ._f5 = _c5, ._s[4] = sizeof(_c5), \
184184+ ._cnt = 5, \
185185+ }; \
186186+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
187187+ __asm__(""); /* avoid tailcall */ \
188188+ _Pragma("clang diagnostic pop") \
189189+})
190190+191191+#define _os_trace_6(_l, _m, _t, _1, _2, _3, _4, _5, _6) __extension__({ \
192192+ _Pragma("clang diagnostic push") \
193193+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
194194+ const __typeof__(_1) _c1 = _1; \
195195+ const __typeof__(_2) _c2 = _2; \
196196+ const __typeof__(_3) _c3 = _3; \
197197+ const __typeof__(_4) _c4 = _4; \
198198+ const __typeof__(_5) _c5 = _5; \
199199+ const __typeof__(_6) _c6 = _6; \
200200+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6); \
201201+ const struct __attribute__((packed)) { \
202202+ __typeof__(_c1) _f1; \
203203+ __typeof__(_c2) _f2; \
204204+ __typeof__(_c3) _f3; \
205205+ __typeof__(_c4) _f4; \
206206+ __typeof__(_c5) _f5; \
207207+ __typeof__(_c6) _f6; \
208208+ uint8_t _s[6]; \
209209+ uint8_t _cnt; \
210210+ } _buf = { \
211211+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
212212+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
213213+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
214214+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
215215+ ._f5 = _c5, ._s[4] = sizeof(_c5), \
216216+ ._f6 = _c6, ._s[5] = sizeof(_c6), \
217217+ ._cnt = 6, \
218218+ }; \
219219+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
220220+ __asm__(""); /* avoid tailcall */ \
221221+ _Pragma("clang diagnostic pop") \
222222+})
223223+224224+#define _os_trace_7(_l, _m, _t, _1, _2, _3, _4, _5, _6, _7) __extension__({ \
225225+ _Pragma("clang diagnostic push") \
226226+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
227227+ const __typeof__(_1) _c1 = _1; \
228228+ const __typeof__(_2) _c2 = _2; \
229229+ const __typeof__(_3) _c3 = _3; \
230230+ const __typeof__(_4) _c4 = _4; \
231231+ const __typeof__(_5) _c5 = _5; \
232232+ const __typeof__(_6) _c6 = _6; \
233233+ const __typeof__(_7) _c7 = _7; \
234234+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6, _c7); \
235235+ const struct __attribute__((packed)) { \
236236+ __typeof__(_c1) _f1; \
237237+ __typeof__(_c2) _f2; \
238238+ __typeof__(_c3) _f3; \
239239+ __typeof__(_c4) _f4; \
240240+ __typeof__(_c5) _f5; \
241241+ __typeof__(_c6) _f6; \
242242+ __typeof__(_c7) _f7; \
243243+ uint8_t _s[7]; \
244244+ uint8_t _cnt; \
245245+ } _buf = { \
246246+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
247247+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
248248+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
249249+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
250250+ ._f5 = _c5, ._s[4] = sizeof(_c5), \
251251+ ._f6 = _c6, ._s[5] = sizeof(_c6), \
252252+ ._f7 = _c7, ._s[6] = sizeof(_c7), \
253253+ ._cnt = 7, \
254254+ }; \
255255+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \
256256+ __asm__(""); /* avoid tailcall */ \
257257+ _Pragma("clang diagnostic pop") \
258258+})
259259+260260+#define _os_trace_with_payload_1(_l, _m, _t, _payload) __extension__({ \
261261+ _os_trace_verify_printf(_l); \
262262+ _os_trace_with_buffer(&__dso_handle, _m, _t, NULL, 0, _payload); \
263263+ __asm__(""); /* avoid tailcall */ \
264264+})
265265+266266+#define _os_trace_with_payload_2(_l, _m, _t, _1, _payload) __extension__({ \
267267+ _Pragma("clang diagnostic push") \
268268+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
269269+ const __typeof__(_1) _c1 = _1; \
270270+ _os_trace_verify_printf(_l, _c1); \
271271+ const struct __attribute__((packed)) { \
272272+ __typeof__(_c1) _f1; \
273273+ uint8_t _s[1]; \
274274+ uint8_t _cnt; \
275275+ } _buf = { \
276276+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
277277+ ._cnt = 1, \
278278+ }; \
279279+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
280280+ __asm__(""); /* avoid tailcall */ \
281281+ _Pragma("clang diagnostic pop") \
282282+})
283283+284284+#define _os_trace_with_payload_3(_l, _m, _t, _1, _2, _payload) __extension__({ \
285285+ _Pragma("clang diagnostic push") \
286286+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
287287+ const __typeof__(_1) _c1 = _1; \
288288+ const __typeof__(_2) _c2 = _2; \
289289+ _os_trace_verify_printf(_l, _c1, _c2); \
290290+ const struct __attribute__((packed)) { \
291291+ __typeof__(_c1) _f1; \
292292+ __typeof__(_c2) _f2; \
293293+ uint8_t _s[2]; \
294294+ uint8_t _cnt; \
295295+ } _buf = { \
296296+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
297297+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
298298+ ._cnt = 2, \
299299+ }; \
300300+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
301301+ __asm__(""); /* avoid tailcall */ \
302302+ _Pragma("clang diagnostic pop") \
303303+})
304304+305305+#define _os_trace_with_payload_4(_l, _m, _t, _1, _2, _3, _payload) __extension__({ \
306306+ _Pragma("clang diagnostic push") \
307307+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
308308+ const __typeof__(_1) _c1 = _1; \
309309+ const __typeof__(_2) _c2 = _2; \
310310+ const __typeof__(_3) _c3 = _3; \
311311+ _os_trace_verify_printf(_l, _c1, _c2, _c3); \
312312+ const struct __attribute__((packed)) { \
313313+ __typeof__(_c1) _f1; \
314314+ __typeof__(_c2) _f2; \
315315+ __typeof__(_c3) _f3; \
316316+ uint8_t _s[3]; \
317317+ uint8_t _cnt; \
318318+ } _buf = { \
319319+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
320320+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
321321+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
322322+ ._cnt = 3, \
323323+ }; \
324324+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
325325+ __asm__(""); /* avoid tailcall */ \
326326+ _Pragma("clang diagnostic pop") \
327327+})
328328+329329+#define _os_trace_with_payload_5(_l, _m, _t, _1, _2, _3, _4, _payload) __extension__({ \
330330+ _Pragma("clang diagnostic push") \
331331+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
332332+ const __typeof__(_1) _c1 = _1; \
333333+ const __typeof__(_2) _c2 = _2; \
334334+ const __typeof__(_3) _c3 = _3; \
335335+ const __typeof__(_4) _c4 = _4; \
336336+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4); \
337337+ const struct __attribute__((packed)) { \
338338+ __typeof__(_c1) _f1; \
339339+ __typeof__(_c2) _f2; \
340340+ __typeof__(_c3) _f3; \
341341+ __typeof__(_c4) _f4; \
342342+ uint8_t _s[4]; \
343343+ uint8_t _cnt; \
344344+ } _buf = { \
345345+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
346346+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
347347+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
348348+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
349349+ ._cnt = 4, \
350350+ }; \
351351+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
352352+ __asm__(""); /* avoid tailcall */ \
353353+ _Pragma("clang diagnostic pop") \
354354+})
355355+356356+#define _os_trace_with_payload_6(_l, _m, _t, _1, _2, _3, _4, _5, _payload) __extension__({ \
357357+ _Pragma("clang diagnostic push") \
358358+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
359359+ const __typeof__(_1) _c1 = _1; \
360360+ const __typeof__(_2) _c2 = _2; \
361361+ const __typeof__(_3) _c3 = _3; \
362362+ const __typeof__(_4) _c4 = _4; \
363363+ const __typeof__(_4) _c5 = _5; \
364364+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5); \
365365+ const struct __attribute__((packed)) { \
366366+ __typeof__(_c1) _f1; \
367367+ __typeof__(_c2) _f2; \
368368+ __typeof__(_c3) _f3; \
369369+ __typeof__(_c4) _f4; \
370370+ __typeof__(_c5) _f5; \
371371+ uint8_t _s[5]; \
372372+ uint8_t _cnt; \
373373+ } _buf = { \
374374+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
375375+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
376376+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
377377+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
378378+ ._f5 = _c5, ._s[4] = sizeof(_c5), \
379379+ ._cnt = 5, \
380380+ }; \
381381+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
382382+ __asm__(""); /* avoid tailcall */ \
383383+ _Pragma("clang diagnostic pop") \
384384+})
385385+386386+#define _os_trace_with_payload_7(_l, _m, _t, _1, _2, _3, _4, _5, _6, _payload) __extension__({ \
387387+ _Pragma("clang diagnostic push") \
388388+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
389389+ const __typeof__(_1) _c1 = _1; \
390390+ const __typeof__(_2) _c2 = _2; \
391391+ const __typeof__(_3) _c3 = _3; \
392392+ const __typeof__(_4) _c4 = _4; \
393393+ const __typeof__(_5) _c5 = _5; \
394394+ const __typeof__(_6) _c6 = _6; \
395395+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6); \
396396+ const struct __attribute__((packed)) { \
397397+ __typeof__(_c1) _f1; \
398398+ __typeof__(_c2) _f2; \
399399+ __typeof__(_c3) _f3; \
400400+ __typeof__(_c4) _f4; \
401401+ __typeof__(_c5) _f5; \
402402+ __typeof__(_c6) _f6; \
403403+ uint8_t _s[6]; \
404404+ uint8_t _cnt; \
405405+ } _buf = { \
406406+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
407407+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
408408+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
409409+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
410410+ ._f5 = _c5, ._s[4] = sizeof(_c5), \
411411+ ._f6 = _c6, ._s[5] = sizeof(_c6), \
412412+ ._cnt = 6, \
413413+ }; \
414414+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
415415+ __asm__(""); /* avoid tailcall */ \
416416+ _Pragma("clang diagnostic pop") \
417417+})
418418+419419+#define _os_trace_with_payload_8(_l, _m, _t, _1, _2, _3, _4, _5, _6, _7, _payload) __extension__({ \
420420+ _Pragma("clang diagnostic push") \
421421+ _Pragma("clang diagnostic ignored \"-Wpacked\"") \
422422+ const __typeof__(_1) _c1 = _1; \
423423+ const __typeof__(_2) _c2 = _2; \
424424+ const __typeof__(_3) _c3 = _3; \
425425+ const __typeof__(_4) _c4 = _4; \
426426+ const __typeof__(_5) _c5 = _5; \
427427+ const __typeof__(_6) _c6 = _6; \
428428+ const __typeof__(_7) _c7 = _7; \
429429+ _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6, _c7); \
430430+ const struct __attribute__((packed)) { \
431431+ __typeof__(_c1) _f1; \
432432+ __typeof__(_c2) _f2; \
433433+ __typeof__(_c3) _f3; \
434434+ __typeof__(_c4) _f4; \
435435+ __typeof__(_c5) _f5; \
436436+ __typeof__(_c6) _f6; \
437437+ __typeof__(_c7) _f7; \
438438+ uint8_t _s[7]; \
439439+ uint8_t _cnt; \
440440+ } _buf = { \
441441+ ._f1 = _c1, ._s[0] = sizeof(_c1), \
442442+ ._f2 = _c2, ._s[1] = sizeof(_c2), \
443443+ ._f3 = _c3, ._s[2] = sizeof(_c3), \
444444+ ._f4 = _c4, ._s[3] = sizeof(_c4), \
445445+ ._f5 = _c5, ._s[4] = sizeof(_c5), \
446446+ ._f6 = _c6, ._s[5] = sizeof(_c6), \
447447+ ._f7 = _c7, ._s[6] = sizeof(_c7), \
448448+ ._cnt = 7, \
449449+ }; \
450450+ _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \
451451+ __asm__(""); /* avoid tailcall */ \
452452+ _Pragma("clang diagnostic pop") \
453453+})
454454+455455+#define OS_TRACE_CALL(format, _m, _t, ...) __extension__({ \
456456+ _Pragma("clang diagnostic push") \
457457+ _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \
458458+ OS_CONCAT(_os_trace, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, _t, ##__VA_ARGS__); \
459459+ _Pragma("clang diagnostic pop") \
460460+})
461461+462462+#else
463463+464464+// Use a new layout in Mac OS 10.12+ and iOS 10.0+
465465+#define OS_TRACE_CALL(_l, _m, _t, ...) __extension__({ \
466466+ uint8_t buf[1024]; \
467467+ _os_trace_verify_printf(_l, ##__VA_ARGS__); \
468468+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, ##__VA_ARGS__); \
469469+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, NULL); \
470470+ __asm__(""); /* avoid tailcall */ \
471471+})
472472+473473+#define _os_trace_with_payload_1(_l, _m, _t, _payload) __extension__({ \
474474+ _os_trace_verify_printf(_l); \
475475+ _os_trace_internal(&__dso_handle, _t, _m, NULL, 0, _payload); \
476476+ __asm__(""); /* avoid tailcall */ \
477477+})
478478+479479+#define _os_trace_with_payload_2(_l, _m, _t, _1, _payload) __extension__({ \
480480+ _os_trace_verify_printf(_l, _1); \
481481+ uint8_t buf[1024]; \
482482+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1); \
483483+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
484484+ __asm__(""); /* avoid tailcall */ \
485485+})
486486+487487+#define _os_trace_with_payload_3(_l, _m, _t, _1, _2, _payload) __extension__({ \
488488+ _os_trace_verify_printf(_l, _1, _2); \
489489+ uint8_t buf[1024]; \
490490+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2); \
491491+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
492492+ __asm__(""); /* avoid tailcall */ \
493493+})
494494+495495+#define _os_trace_with_payload_4(_l, _m, _t, _1, _2, _3, _payload) __extension__({ \
496496+ _os_trace_verify_printf(_l, _1, _2, _3); \
497497+ uint8_t buf[1024]; \
498498+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3); \
499499+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
500500+ __asm__(""); /* avoid tailcall */ \
501501+})
502502+503503+#define _os_trace_with_payload_5(_l, _m, _t, _1, _2, _3, _4, _payload) __extension__({ \
504504+ _os_trace_verify_printf(_l, _1, _2, _3, _4); \
505505+ uint8_t buf[1024]; \
506506+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4); \
507507+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
508508+ __asm__(""); /* avoid tailcall */ \
509509+})
510510+511511+#define _os_trace_with_payload_6(_l, _m, _t, _1, _2, _3, _4, _5, _payload) __extension__({ \
512512+ _os_trace_verify_printf(_l, _1, _2, _3, _4, _5); \
513513+ uint8_t buf[1024]; \
514514+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4, _5); \
515515+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
516516+ __asm__(""); /* avoid tailcall */ \
517517+})
518518+519519+#define _os_trace_with_payload_7(_l, _m, _t, _1, _2, _3, _4, _5, _6, _payload) __extension__({ \
520520+ _os_trace_verify_printf(_l, _1, _2, _3, _4, _5, _6); \
521521+ uint8_t buf[1024]; \
522522+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4, _5, _6); \
523523+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
524524+ __asm__(""); /* avoid tailcall */ \
525525+})
526526+527527+#define _os_trace_with_payload_8(_l, _m, _t, _1, _2, _3, _4, _5, _6, _7, _payload) __extension__({ \
528528+ _os_trace_verify_printf(_l, _1, _2, _3, _4, _5, _6, _7); \
529529+ uint8_t buf[1024]; \
530530+ size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4, _5, _6, _7); \
531531+ _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \
532532+ __asm__(""); /* avoid tailcall */ \
533533+})
534534+535535+#endif /* if Mac OS >= 10.12 or iPhone OS >= 10.0 */
536536+537537+/*!
538538+ *
539539+ * @abstract
540540+ * Hashtags in trace messages
541541+ *
542542+ * @discussion
543543+ * Developers are encouraged to include hashtags in log messages, regardless of what API you use.
544544+ * A hashtag is composed of a hash (#) symbol, followed by at least three non-whitespace characters,
545545+ * terminated by whitespace or the end of the message. Hashtags may not begin with a number.
546546+ *
547547+ * Below is the list of predefined tags:
548548+ * #System - Message in the context of a system process.
549549+ * #User - Message in the context of a user process.
550550+ * #Developer - Message in the context of software development. For example, deprecated APIs and debugging messages.
551551+ * #Attention - Message that should be investigated by a system administrator, because it may be a sign of a larger issue.
552552+ * For example, errors from a hard drive controller that typically occur when the drive is about to fail.
553553+ * #Critical - Message in the context of a critical event or critical failure.
554554+ * #Error - Message that is a noncritical error.
555555+ * #Comment - Message that is a comment.
556556+ * #Marker - Message that marks a change to divide the messages around it into those before and those after the change.
557557+ * #Clue - Message containing extra key/value pairs with additional information to help reconstruct the context.
558558+ * #Security - Message related to security concerns.
559559+ * #Filesystem - Message describing a file system related event.
560560+ * #Network - Message describing a network-related event.
561561+ * #Hardware - Message describing a hardware-related event.
562562+ * #CPU - Message describing CPU related event, e.g., initiating heavy work load
563563+ * #State - Message describing state changed, e.g., global state, preference, etc.
564564+ * #Graphics - Message describing significant graphics event
565565+ * #Disk - Message describing disk activity
566566+ *
567567+ */
568568+569569+#pragma mark - Other defines
570570+571571+/*!
572572+ * @define OS_TRACE_TYPE_RELEASE
573573+ * Trace messages to be captured on a typical user install. These should be
574574+ * limited to things which improve diagnosis of a failure/crash/hang. Trace
575575+ * buffers are generally smaller on a production system.
576576+ */
577577+#define OS_TRACE_TYPE_RELEASE (1u << 0)
578578+579579+/*!
580580+ * @define OS_TRACE_TYPE_DEBUG
581581+ * Trace messages to be captured while debugger or other development tool is
582582+ * attached to the originator.
583583+ */
584584+#define OS_TRACE_TYPE_DEBUG (1u << 1)
585585+586586+/*!
587587+ * @define OS_TRACE_TYPE_INFO
588588+ * Trace messages that are captured when a debugger is attached, system or
589589+ * Application mode has been increased to include additional information.
590590+ */
591591+#define OS_TRACE_TYPE_INFO (1u << 2)
592592+593593+/*!
594594+ * @define OS_TRACE_TYPE_ERROR
595595+ * Trace the message as an error and force a collection as a failure may be
596596+ * imminent.
597597+ */
598598+#define OS_TRACE_TYPE_ERROR ((1u << 6) | (1u << 0))
599599+600600+/*!
601601+ * @define OS_TRACE_TYPE_FAULT
602602+ * Trace the message as a fatal error which forces a collection and a diagnostic
603603+ * to be initiated.
604604+ */
605605+#define OS_TRACE_TYPE_FAULT ((1u << 7) | (1u << 6) | (1u << 0))
606606+607607+/*!
608608+ * @typedef os_trace_payload_t
609609+ * A block that populates an xpc_object_t of type XPC_TYPE_DICTIONARY to represent
610610+ * complex data. This block will only be invoked under conditions where tools
611611+ * have attached to the process. The payload can be used to send arbitrary data
612612+ * via the trace call. Tools may use the data to validate state for integration
613613+ * tests or provide other introspection services. No assumptions are made about
614614+ * the format or structure of the data.
615615+ */
616616+typedef void (^os_trace_payload_t)(xpc_object_t xdict);
617617+618618+#pragma mark - function declarations
619619+620620+/*!
621621+ * @function os_trace
622622+ *
623623+ * @abstract
624624+ * Always inserts a trace message into a buffer pool for later decoding.
625625+ *
626626+ * @discussion
627627+ * Trace message that will be recorded on a typical user install. These should
628628+ * be limited to things which help diagnose a failure during postmortem
629629+ * analysis. Trace buffers are generally smaller on a production system.
630630+ *
631631+ * @param format
632632+ * A printf-style format string to generate a human-readable log message when
633633+ * the trace line is decoded. Only scalar types are supported, attempts
634634+ * to pass arbitrary strings will store a pointer that is unresolvable and
635635+ * will generate an error during decode.
636636+ *
637637+ * os_trace("network event: %ld, last seen: %ld, avg: %g", event_id, last_seen, avg);
638638+ */
639639+#define os_trace(format, ...) __extension__({ \
640640+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
641641+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
642642+ OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_RELEASE, ##__VA_ARGS__); \
643643+})
644644+645645+646646+#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_10_0) \
647647+ || (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED >= __WATCHOS_3_0) \
648648+ || (defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED >= __TVOS_10_0) \
649649+ || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_12)
650650+651651+/*!
652652+ * @function os_trace_info
653653+ *
654654+ * @abstract
655655+ * Optionally inserts a trace message containing additional information into a
656656+ * buffer pool for later decoding.
657657+ *
658658+ * @discussion
659659+ * Trace messages that will be captured when additional information is needed
660660+ * and are not captured by default. They will only be captured if the
661661+ * system/process/activity mode has been increased or if a Development tool has
662662+ * been attached to the process.
663663+ *
664664+ * @param format
665665+ * A printf-style format string that represents a human-readable message when
666666+ * the trace line is decoded. Only scalar types are supported, attempts
667667+ * to pass arbitrary strings will store a pointer that is unresolvable and
668668+ * will generate an error during decode.
669669+ *
670670+ * os_trace_info("network interface status %ld", status);
671671+ */
672672+#define os_trace_info(format, ...) __extension__({ \
673673+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
674674+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
675675+ OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_INFO, ##__VA_ARGS__); \
676676+})
677677+678678+#endif
679679+680680+/*!
681681+ * @function os_trace_debug
682682+ *
683683+ * @abstract
684684+ * Insert debug trace message into a buffer pool for later decoding.
685685+ *
686686+ * @discussion
687687+ * Debug trace message to be recorded while debugger or other development tool is
688688+ * attached to the originator. This is transported interprocess to help
689689+ * diagnose the entire call chain including external helpers.
690690+ *
691691+ * @param format
692692+ * A printf-style format string that represents a human-readable message when
693693+ * the trace line is decoded. Only scalar types are supported, attempts
694694+ * to pass arbitrary strings will store a pointer that is unresolvable and
695695+ * will generate an error during decode.
696696+ *
697697+ * os_trace_debug("network interface status %ld", status);
698698+ */
699699+#define os_trace_debug(format, ...) __extension__({ \
700700+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
701701+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
702702+ OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_DEBUG, ##__VA_ARGS__); \
703703+})
704704+705705+/*!
706706+ * @function os_trace_info_enabled
707707+ *
708708+ * @abstract
709709+ * Avoid unnecessary work for a trace point by checking if additional information
710710+ * is enabled.
711711+ *
712712+ * @discussion
713713+ * Avoid unnecessary work for a trace point by checking if additional information
714714+ * is enabled. Generally trace points should not involve expensive operations, but some
715715+ * circumstances warrant it. Use this function to avoid doing the work unless
716716+ * debug level trace messages are requested.
717717+ *
718718+ * if (os_trace_info_enabled()) {
719719+ * os_trace_info("value = %d, average = %d",
720720+ * [[dict objectForKey: @"myKey"] intValue],
721721+ * (int) [self getAverage: dict]);
722722+ * }
723723+ *
724724+ * @result
725725+ * Returns true if development mode is enabled.
726726+ */
727727+__OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0)
728728+OS_EXPORT OS_NOTHROW OS_WARN_RESULT
729729+bool
730730+os_trace_info_enabled(void);
731731+732732+/*!
733733+ * @function os_trace_debug_enabled
734734+ *
735735+ * @abstract
736736+ * Avoid unnecessary work for a trace point by checking if debug level is enabled.
737737+ *
738738+ * @discussion
739739+ * Avoid unnecessary work for a trace point by checking if debug level is enabled.
740740+ * Generally trace points should not involve expensive operations, but some
741741+ * circumstances warrant it. Use this function to avoid doing the work unless
742742+ * debug level trace messages are requested.
743743+ *
744744+ * if (os_trace_debug_enabled()) {
745745+ * os_trace_debug("value = %d, average = %d",
746746+ * [[dict objectForKey: @"myKey"] intValue],
747747+ * (int) [self getAverage: dict]);
748748+ * }
749749+ *
750750+ * @result
751751+ * Returns true if debug mode is enabled.
752752+ */
753753+__OSX_AVAILABLE(10.10) __IOS_AVAILABLE(8.0) __WATCHOS_AVAILABLE(1.0) __TVOS_AVAILABLE(9.0)
754754+OS_EXPORT OS_NOTHROW OS_WARN_RESULT
755755+bool
756756+os_trace_debug_enabled(void);
757757+758758+/*!
759759+ * @function os_trace_error
760760+ *
761761+ * @abstract
762762+ * Trace the message as an error and force a collection of the trace buffer as a
763763+ * failure may be imminent.
764764+ *
765765+ * @discussion
766766+ * Trace the message as an error and force a collection of the trace buffer as a
767767+ * failure may be imminent.
768768+ *
769769+ * @param format
770770+ * A printf-style format string to generate a human-readable log message when
771771+ * the trace line is decoded. Only scalar types are supported, attempts
772772+ * to pass arbitrary strings will store a pointer that is unresolvable and
773773+ * will generate an error during decode.
774774+ *
775775+ * os_trace_error("socket %d connection timeout %ld", fd, secs);
776776+ */
777777+#define os_trace_error(format, ...) __extension__({ \
778778+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
779779+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
780780+ OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_ERROR, ##__VA_ARGS__); \
781781+})
782782+783783+/*!
784784+ * @function os_trace_fault
785785+ *
786786+ * @abstract
787787+ * Trace the message as a fault which forces a collection of the trace buffer
788788+ * and diagnostic of the activity.
789789+ *
790790+ * @discussion
791791+ * Trace the message as a fault which forces a collection of the trace buffer
792792+ * and diagnostic of the activity.
793793+ *
794794+ * @param format
795795+ * A printf-style format string to generate a human-readable log message when
796796+ * the trace line is decoded. Only scalar types are supported, attempts
797797+ * to pass arbitrary strings will store a pointer that is unresolvable and
798798+ * will generate an error during decode.
799799+ *
800800+ * os_trace_fault("failed to lookup uid %d - aborting", uid);
801801+ */
802802+#define os_trace_fault(format, ...) __extension__({ \
803803+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
804804+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
805805+ OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_FAULT, ##__VA_ARGS__); \
806806+})
807807+808808+#if __has_include(<xpc/xpc.h>)
809809+/*!
810810+ * @function os_trace_with_payload
811811+ *
812812+ * @abstract
813813+ * Add a trace entry containing the provided values and call the block if
814814+ * appropriate.
815815+ *
816816+ * @discussion
817817+ * Will insert a trace entry into a limited ring buffer for an activity or
818818+ * process. Trace points are for recording interesting data that would improve
819819+ * diagnosis of unexpected crashes, failures and hangs. The block will only be
820820+ * called under the required conditions.
821821+ *
822822+ * @param trace_msg
823823+ * A printf-style format string to generate a human-readable log message when
824824+ * the trace line is decoded. Only scalar types are supported. Attempts
825825+ * to pass arbitrary strings will store a pointer that is unresolvable and
826826+ * will generate an error during decode.
827827+ *
828828+ * The final parameter must be a block of type os_trace_payload_t.
829829+ *
830830+ * os_trace_with_payload("network event %ld", event, ^(xpc_object_t xdict) {
831831+ *
832832+ * // validate the network interface and address where what was expected
833833+ * xpc_dictionary_set_string(xdict, "network", ifp->ifa_name);
834834+ * xpc_dictionary_set_string(xdict, "ip_address", _get_address(ifp));
835835+ * });
836836+ */
837837+#define os_trace_with_payload(format, ...) __extension__({ \
838838+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
839839+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
840840+ OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_RELEASE, ##__VA_ARGS__); \
841841+})
842842+843843+#define os_trace_info_with_payload(format, ...) __extension__({ \
844844+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
845845+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
846846+ OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_INFO, ##__VA_ARGS__); \
847847+})
848848+849849+#define os_trace_debug_with_payload(format, ...) __extension__({ \
850850+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
851851+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
852852+ OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_DEBUG, ##__VA_ARGS__); \
853853+})
854854+855855+#define os_trace_error_with_payload(format, ...) __extension__({ \
856856+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
857857+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
858858+ OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_ERROR, ##__VA_ARGS__); \
859859+})
860860+861861+#define os_trace_fault_with_payload(format, ...) __extension__({ \
862862+ _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \
863863+ __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \
864864+ OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_FAULT, ##__VA_ARGS__); \
865865+})
866866+867867+#endif // __has_include(<xpc/xpc.h>)
868868+869869+// TODO: change this once we have compiler support
870870+__OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0)
871871+OS_EXPORT OS_NOTHROW
872872+size_t
873873+_os_trace_encode(uint8_t *buf, size_t buf_size, const char *format, ...);
874874+875875+__OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0)
876876+OS_EXPORT OS_NOTHROW
877877+void
878878+_os_trace_internal(void *dso, uint8_t type, const char *format, const uint8_t *buf, size_t buf_size, os_trace_payload_t payload);
879879+880880+/*!
881881+ * @function _os_trace_with_buffer
882882+ *
883883+ * @abstract
884884+ * Internal function to support pre-encoded buffer.
885885+ */
886886+__OSX_AVAILABLE(10.10) __IOS_AVAILABLE(8.0) __WATCHOS_AVAILABLE(1.0) __TVOS_AVAILABLE(9.0)
887887+OS_EXPORT OS_NOTHROW
888888+void
889889+_os_trace_with_buffer(void *dso, const char *message, uint8_t type, const void *buffer, size_t buffer_size, os_trace_payload_t payload);
890890+891891+__END_DECLS
892892+893893+#endif // __OS_TRACE_H__
···11// This function is called from _gai_addr_sort()
22-// No implementation seems to be available.
22+// On macOS, it resides in libsystem_network.dylib, which is not open source.
3344int sa_dst_compare()
55{
···3434 void *ptr;
3535};
36363737+// XXX: I had to add an initializer here. Without it, the symbol wasn't being exported
3738__attribute__((visibility("default")))
3839extern struct _os_alloc_once_s _os_alloc_once_table[];
3939-struct _os_alloc_once_s _os_alloc_once_table[OS_ALLOC_ONCE_KEY_MAX];
4040+struct _os_alloc_once_s _os_alloc_once_table[OS_ALLOC_ONCE_KEY_MAX] = { {0,0} };