xref: /xnu-10063.121.3/libkern/os/log_encode.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /*
2*2c2f96dcSApple OSS Distributions  * Copyright (c) 2015-2020 Apple Inc. All rights reserved.
3*2c2f96dcSApple OSS Distributions  *
4*2c2f96dcSApple OSS Distributions  * @APPLE_LICENSE_HEADER_START@
5*2c2f96dcSApple OSS Distributions  *
6*2c2f96dcSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*2c2f96dcSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*2c2f96dcSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*2c2f96dcSApple OSS Distributions  * compliance with the License. Please obtain a copy of the License at
10*2c2f96dcSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this
11*2c2f96dcSApple OSS Distributions  * file.
12*2c2f96dcSApple OSS Distributions  *
13*2c2f96dcSApple OSS Distributions  * The Original Code and all software distributed under the License are
14*2c2f96dcSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*2c2f96dcSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*2c2f96dcSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*2c2f96dcSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*2c2f96dcSApple OSS Distributions  * Please see the License for the specific language governing rights and
19*2c2f96dcSApple OSS Distributions  * limitations under the License.
20*2c2f96dcSApple OSS Distributions  *
21*2c2f96dcSApple OSS Distributions  * @APPLE_LICENSE_HEADER_END@
22*2c2f96dcSApple OSS Distributions  */
23*2c2f96dcSApple OSS Distributions 
24*2c2f96dcSApple OSS Distributions #include <stdbool.h>
25*2c2f96dcSApple OSS Distributions #include <firehose/tracepoint_private.h>
26*2c2f96dcSApple OSS Distributions #include <kern/assert.h>
27*2c2f96dcSApple OSS Distributions #include <kern/counter.h>
28*2c2f96dcSApple OSS Distributions #include <kern/locks.h>
29*2c2f96dcSApple OSS Distributions #include <pexpert/pexpert.h>
30*2c2f96dcSApple OSS Distributions #include <sys/param.h>
31*2c2f96dcSApple OSS Distributions 
32*2c2f96dcSApple OSS Distributions #if __has_feature(ptrauth_calls)
33*2c2f96dcSApple OSS Distributions #include <mach/vm_param.h>
34*2c2f96dcSApple OSS Distributions #include <ptrauth.h>
35*2c2f96dcSApple OSS Distributions #endif /* __has_feature(ptrauth_calls) */
36*2c2f96dcSApple OSS Distributions 
37*2c2f96dcSApple OSS Distributions #include "log_encode.h"
38*2c2f96dcSApple OSS Distributions #include "log_internal.h"
39*2c2f96dcSApple OSS Distributions #include "log_mem.h"
40*2c2f96dcSApple OSS Distributions 
41*2c2f96dcSApple OSS Distributions #define LOG_FMT_MAX_PRECISION (1024)
42*2c2f96dcSApple OSS Distributions #define log_context_cursor(ctx) &(ctx)->ctx_hdr->hdr_data[(ctx)->ctx_content_off]
43*2c2f96dcSApple OSS Distributions #define TRACEPOINT_BUF_MAX_SIZE (64)
44*2c2f96dcSApple OSS Distributions 
45*2c2f96dcSApple OSS Distributions typedef struct {
46*2c2f96dcSApple OSS Distributions 	uint8_t *tp_buf;
47*2c2f96dcSApple OSS Distributions 	size_t  tp_size;
48*2c2f96dcSApple OSS Distributions } tracepoint_buf_t;
49*2c2f96dcSApple OSS Distributions 
50*2c2f96dcSApple OSS Distributions SCALABLE_COUNTER_DEFINE(oslog_p_fmt_invalid_msgcount);
51*2c2f96dcSApple OSS Distributions SCALABLE_COUNTER_DEFINE(oslog_p_fmt_max_args_msgcount);
52*2c2f96dcSApple OSS Distributions SCALABLE_COUNTER_DEFINE(oslog_p_truncated_msgcount);
53*2c2f96dcSApple OSS Distributions 
54*2c2f96dcSApple OSS Distributions extern boolean_t doprnt_hide_pointers;
55*2c2f96dcSApple OSS Distributions 
56*2c2f96dcSApple OSS Distributions static bool
is_digit(char ch)57*2c2f96dcSApple OSS Distributions is_digit(char ch)
58*2c2f96dcSApple OSS Distributions {
59*2c2f96dcSApple OSS Distributions 	return (ch >= '0') && (ch <= '9');
60*2c2f96dcSApple OSS Distributions }
61*2c2f96dcSApple OSS Distributions 
62*2c2f96dcSApple OSS Distributions static bool
is_kernel_pointer(void * arg,size_t arg_len)63*2c2f96dcSApple OSS Distributions is_kernel_pointer(void *arg, size_t arg_len)
64*2c2f96dcSApple OSS Distributions {
65*2c2f96dcSApple OSS Distributions 	if (arg_len < sizeof(void *)) {
66*2c2f96dcSApple OSS Distributions 		return false;
67*2c2f96dcSApple OSS Distributions 	}
68*2c2f96dcSApple OSS Distributions 
69*2c2f96dcSApple OSS Distributions 	unsigned long long value = 0;
70*2c2f96dcSApple OSS Distributions 	assert(arg_len <= sizeof(value));
71*2c2f96dcSApple OSS Distributions 	(void) memcpy(&value, arg, arg_len);
72*2c2f96dcSApple OSS Distributions 
73*2c2f96dcSApple OSS Distributions #if __has_feature(ptrauth_calls)
74*2c2f96dcSApple OSS Distributions 	/**
75*2c2f96dcSApple OSS Distributions 	 * Strip out the pointer authentication code before
76*2c2f96dcSApple OSS Distributions 	 * checking whether the pointer is a kernel address.
77*2c2f96dcSApple OSS Distributions 	 */
78*2c2f96dcSApple OSS Distributions 	value = (unsigned long long)VM_KERNEL_STRIP_PTR(value);
79*2c2f96dcSApple OSS Distributions #endif /* __has_feature(ptrauth_calls) */
80*2c2f96dcSApple OSS Distributions 
81*2c2f96dcSApple OSS Distributions 	return value >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && value <= VM_MAX_KERNEL_ADDRESS;
82*2c2f96dcSApple OSS Distributions }
83*2c2f96dcSApple OSS Distributions 
84*2c2f96dcSApple OSS Distributions static void
log_context_cursor_advance(os_log_context_t ctx,size_t amount)85*2c2f96dcSApple OSS Distributions log_context_cursor_advance(os_log_context_t ctx, size_t amount)
86*2c2f96dcSApple OSS Distributions {
87*2c2f96dcSApple OSS Distributions 	ctx->ctx_content_off += amount;
88*2c2f96dcSApple OSS Distributions 	assert(log_context_cursor(ctx) <= (ctx->ctx_buffer + ctx->ctx_buffer_sz));
89*2c2f96dcSApple OSS Distributions }
90*2c2f96dcSApple OSS Distributions 
91*2c2f96dcSApple OSS Distributions static bool
log_fits(os_log_context_t ctx,size_t data_size)92*2c2f96dcSApple OSS Distributions log_fits(os_log_context_t ctx, size_t data_size)
93*2c2f96dcSApple OSS Distributions {
94*2c2f96dcSApple OSS Distributions 	return (ctx->ctx_content_off + data_size) <= ctx->ctx_content_sz;
95*2c2f96dcSApple OSS Distributions }
96*2c2f96dcSApple OSS Distributions 
97*2c2f96dcSApple OSS Distributions static bool
log_fits_cmd(os_log_context_t ctx,size_t data_size)98*2c2f96dcSApple OSS Distributions log_fits_cmd(os_log_context_t ctx, size_t data_size)
99*2c2f96dcSApple OSS Distributions {
100*2c2f96dcSApple OSS Distributions 	return log_fits(ctx, sizeof(*ctx->ctx_hdr) + data_size);
101*2c2f96dcSApple OSS Distributions }
102*2c2f96dcSApple OSS Distributions 
103*2c2f96dcSApple OSS Distributions static void
log_range_update(os_log_fmt_range_t range,uint16_t offset,uint16_t length)104*2c2f96dcSApple OSS Distributions log_range_update(os_log_fmt_range_t range, uint16_t offset, uint16_t length)
105*2c2f96dcSApple OSS Distributions {
106*2c2f96dcSApple OSS Distributions 	range->offset = offset;
107*2c2f96dcSApple OSS Distributions 	/*
108*2c2f96dcSApple OSS Distributions 	 * Truncated flag may have already been set earlier, hence do not
109*2c2f96dcSApple OSS Distributions 	 * overwrite it blindly.
110*2c2f96dcSApple OSS Distributions 	 */
111*2c2f96dcSApple OSS Distributions 	if (length < range->length) {
112*2c2f96dcSApple OSS Distributions 		range->truncated = true;
113*2c2f96dcSApple OSS Distributions 	}
114*2c2f96dcSApple OSS Distributions 	range->length = length;
115*2c2f96dcSApple OSS Distributions }
116*2c2f96dcSApple OSS Distributions 
117*2c2f96dcSApple OSS Distributions /*
118*2c2f96dcSApple OSS Distributions  * Stores a command in the main section. The value itself is wrapped in
119*2c2f96dcSApple OSS Distributions  * the os_log_fmt_cmd_t struct.
120*2c2f96dcSApple OSS Distributions  */
121*2c2f96dcSApple OSS Distributions static void
log_add_cmd(os_log_context_t ctx,os_log_fmt_cmd_type_t type,uint8_t flags,void * arg,size_t arg_size)122*2c2f96dcSApple OSS Distributions log_add_cmd(os_log_context_t ctx, os_log_fmt_cmd_type_t type, uint8_t flags,
123*2c2f96dcSApple OSS Distributions     void *arg, size_t arg_size)
124*2c2f96dcSApple OSS Distributions {
125*2c2f96dcSApple OSS Distributions 	os_log_fmt_cmd_t cmd;
126*2c2f96dcSApple OSS Distributions 	const size_t cmd_sz = sizeof(*cmd) + arg_size;
127*2c2f96dcSApple OSS Distributions 
128*2c2f96dcSApple OSS Distributions 	assert(log_fits_cmd(ctx, cmd_sz));
129*2c2f96dcSApple OSS Distributions 	assert(arg_size <= UINT8_MAX);
130*2c2f96dcSApple OSS Distributions 
131*2c2f96dcSApple OSS Distributions 	cmd = (os_log_fmt_cmd_t)log_context_cursor(ctx);
132*2c2f96dcSApple OSS Distributions 	cmd->cmd_type = type;
133*2c2f96dcSApple OSS Distributions 	cmd->cmd_flags = flags;
134*2c2f96dcSApple OSS Distributions 	cmd->cmd_size = (uint8_t)arg_size;
135*2c2f96dcSApple OSS Distributions 	(void) memcpy(cmd->cmd_data, arg, cmd->cmd_size);
136*2c2f96dcSApple OSS Distributions 
137*2c2f96dcSApple OSS Distributions 	assert(cmd_sz == sizeof(*cmd) + cmd->cmd_size);
138*2c2f96dcSApple OSS Distributions 	log_context_cursor_advance(ctx, cmd_sz);
139*2c2f96dcSApple OSS Distributions }
140*2c2f96dcSApple OSS Distributions 
141*2c2f96dcSApple OSS Distributions /*
142*2c2f96dcSApple OSS Distributions  * Collect details about argument which needs to be stored in the pubdata
143*2c2f96dcSApple OSS Distributions  * section.
144*2c2f96dcSApple OSS Distributions  */
145*2c2f96dcSApple OSS Distributions static void
log_collect_public_range_data(os_log_context_t ctx,os_log_fmt_range_t range,void * arg)146*2c2f96dcSApple OSS Distributions log_collect_public_range_data(os_log_context_t ctx, os_log_fmt_range_t range, void *arg)
147*2c2f96dcSApple OSS Distributions {
148*2c2f96dcSApple OSS Distributions 	ctx->ctx_pubdata[ctx->ctx_pubdata_cnt++] = (char *)arg;
149*2c2f96dcSApple OSS Distributions 	ctx->ctx_pubdata_sz += range->length;
150*2c2f96dcSApple OSS Distributions }
151*2c2f96dcSApple OSS Distributions 
152*2c2f96dcSApple OSS Distributions static void
log_add_range_data(os_log_context_t ctx,os_log_fmt_range_t range,void * arg)153*2c2f96dcSApple OSS Distributions log_add_range_data(os_log_context_t ctx, os_log_fmt_range_t range, void *arg)
154*2c2f96dcSApple OSS Distributions {
155*2c2f96dcSApple OSS Distributions 	assert(log_fits(ctx, range->length));
156*2c2f96dcSApple OSS Distributions 	(void) memcpy(log_context_cursor(ctx), arg, range->length);
157*2c2f96dcSApple OSS Distributions 	log_context_cursor_advance(ctx, range->length);
158*2c2f96dcSApple OSS Distributions }
159*2c2f96dcSApple OSS Distributions 
160*2c2f96dcSApple OSS Distributions static struct os_log_fmt_range_s
log_create_range(os_log_context_t ctx,size_t arg_len)161*2c2f96dcSApple OSS Distributions log_create_range(os_log_context_t ctx, size_t arg_len)
162*2c2f96dcSApple OSS Distributions {
163*2c2f96dcSApple OSS Distributions 	const size_t final_arg_len = MIN(arg_len, UINT16_MAX);
164*2c2f96dcSApple OSS Distributions 
165*2c2f96dcSApple OSS Distributions 	return (struct os_log_fmt_range_s) {
166*2c2f96dcSApple OSS Distributions 		       .offset = ctx->ctx_pubdata_sz,
167*2c2f96dcSApple OSS Distributions 		       .length = (uint16_t)final_arg_len,
168*2c2f96dcSApple OSS Distributions 		       .truncated = (final_arg_len < arg_len)
169*2c2f96dcSApple OSS Distributions 	};
170*2c2f96dcSApple OSS Distributions }
171*2c2f96dcSApple OSS Distributions 
172*2c2f96dcSApple OSS Distributions static int
log_add_range_arg(os_log_context_t ctx,os_log_fmt_cmd_type_t type,os_log_fmt_cmd_flags_t flags,void * arg,size_t arg_len)173*2c2f96dcSApple OSS Distributions log_add_range_arg(os_log_context_t ctx, os_log_fmt_cmd_type_t type, os_log_fmt_cmd_flags_t flags,
174*2c2f96dcSApple OSS Distributions     void *arg, size_t arg_len)
175*2c2f96dcSApple OSS Distributions {
176*2c2f96dcSApple OSS Distributions 	struct os_log_fmt_range_s range;
177*2c2f96dcSApple OSS Distributions 
178*2c2f96dcSApple OSS Distributions 	if (!log_fits_cmd(ctx, sizeof(range))) {
179*2c2f96dcSApple OSS Distributions 		return ENOMEM;
180*2c2f96dcSApple OSS Distributions 	}
181*2c2f96dcSApple OSS Distributions 
182*2c2f96dcSApple OSS Distributions 	range = log_create_range(ctx, arg_len);
183*2c2f96dcSApple OSS Distributions 
184*2c2f96dcSApple OSS Distributions 	if (flags == OSLF_CMD_FLAG_PUBLIC) {
185*2c2f96dcSApple OSS Distributions 		if (ctx->ctx_pubdata_cnt == OS_LOG_MAX_PUB_ARGS) {
186*2c2f96dcSApple OSS Distributions 			return ENOMEM;
187*2c2f96dcSApple OSS Distributions 		}
188*2c2f96dcSApple OSS Distributions 		assert(ctx->ctx_pubdata_cnt < OS_LOG_MAX_PUB_ARGS);
189*2c2f96dcSApple OSS Distributions 		log_collect_public_range_data(ctx, &range, arg);
190*2c2f96dcSApple OSS Distributions 	}
191*2c2f96dcSApple OSS Distributions 	log_add_cmd(ctx, type, flags, &range, sizeof(range));
192*2c2f96dcSApple OSS Distributions 	ctx->ctx_hdr->hdr_cmd_cnt++;
193*2c2f96dcSApple OSS Distributions 
194*2c2f96dcSApple OSS Distributions 	return 0;
195*2c2f96dcSApple OSS Distributions }
196*2c2f96dcSApple OSS Distributions 
197*2c2f96dcSApple OSS Distributions /*
198*2c2f96dcSApple OSS Distributions  * Adds a scalar argument value to the main section.
199*2c2f96dcSApple OSS Distributions  */
200*2c2f96dcSApple OSS Distributions static int
log_add_arg(os_log_context_t ctx,os_log_fmt_cmd_type_t type,void * arg,size_t arg_len)201*2c2f96dcSApple OSS Distributions log_add_arg(os_log_context_t ctx, os_log_fmt_cmd_type_t type, void *arg, size_t arg_len)
202*2c2f96dcSApple OSS Distributions {
203*2c2f96dcSApple OSS Distributions 	assert(type == OSLF_CMD_TYPE_COUNT || type == OSLF_CMD_TYPE_SCALAR);
204*2c2f96dcSApple OSS Distributions 	assert(arg_len < UINT16_MAX);
205*2c2f96dcSApple OSS Distributions 
206*2c2f96dcSApple OSS Distributions 	if (log_fits_cmd(ctx, arg_len)) {
207*2c2f96dcSApple OSS Distributions 		log_add_cmd(ctx, type, OSLF_CMD_FLAG_PUBLIC, arg, arg_len);
208*2c2f96dcSApple OSS Distributions 		ctx->ctx_hdr->hdr_cmd_cnt++;
209*2c2f96dcSApple OSS Distributions 		return 0;
210*2c2f96dcSApple OSS Distributions 	}
211*2c2f96dcSApple OSS Distributions 
212*2c2f96dcSApple OSS Distributions 	return ENOMEM;
213*2c2f96dcSApple OSS Distributions }
214*2c2f96dcSApple OSS Distributions 
215*2c2f96dcSApple OSS Distributions static void
log_encode_public_data(os_log_context_t ctx)216*2c2f96dcSApple OSS Distributions log_encode_public_data(os_log_context_t ctx)
217*2c2f96dcSApple OSS Distributions {
218*2c2f96dcSApple OSS Distributions 	const uint16_t orig_content_off = ctx->ctx_content_off;
219*2c2f96dcSApple OSS Distributions 	os_log_fmt_hdr_t const hdr = ctx->ctx_hdr;
220*2c2f96dcSApple OSS Distributions 	os_log_fmt_cmd_t cmd = (os_log_fmt_cmd_t)hdr->hdr_data;
221*2c2f96dcSApple OSS Distributions 
222*2c2f96dcSApple OSS Distributions 	assert(ctx->ctx_pubdata_cnt <= hdr->hdr_cmd_cnt);
223*2c2f96dcSApple OSS Distributions 
224*2c2f96dcSApple OSS Distributions 	for (int i = 0, pub_i = 0; i < hdr->hdr_cmd_cnt; i++, cmd = (os_log_fmt_cmd_t)(cmd->cmd_data + cmd->cmd_size)) {
225*2c2f96dcSApple OSS Distributions 		if (cmd->cmd_type != OSLF_CMD_TYPE_STRING) {
226*2c2f96dcSApple OSS Distributions 			continue;
227*2c2f96dcSApple OSS Distributions 		}
228*2c2f96dcSApple OSS Distributions 
229*2c2f96dcSApple OSS Distributions 		os_log_fmt_range_t const range __attribute__((aligned(8))) = (os_log_fmt_range_t)&cmd->cmd_data;
230*2c2f96dcSApple OSS Distributions 
231*2c2f96dcSApple OSS Distributions 		// Fix offset and length of the argument data in the hdr.
232*2c2f96dcSApple OSS Distributions 		log_range_update(range, ctx->ctx_content_off - orig_content_off,
233*2c2f96dcSApple OSS Distributions 		    MIN(range->length, ctx->ctx_content_sz - ctx->ctx_content_off));
234*2c2f96dcSApple OSS Distributions 
235*2c2f96dcSApple OSS Distributions 		if (range->truncated) {
236*2c2f96dcSApple OSS Distributions 			ctx->ctx_truncated = true;
237*2c2f96dcSApple OSS Distributions 		}
238*2c2f96dcSApple OSS Distributions 
239*2c2f96dcSApple OSS Distributions 		assert(pub_i < ctx->ctx_pubdata_cnt);
240*2c2f96dcSApple OSS Distributions 		log_add_range_data(ctx, range, ctx->ctx_pubdata[pub_i++]);
241*2c2f96dcSApple OSS Distributions 	}
242*2c2f96dcSApple OSS Distributions }
243*2c2f96dcSApple OSS Distributions 
244*2c2f96dcSApple OSS Distributions static bool
log_expand(os_log_context_t ctx,size_t new_size)245*2c2f96dcSApple OSS Distributions log_expand(os_log_context_t ctx, size_t new_size)
246*2c2f96dcSApple OSS Distributions {
247*2c2f96dcSApple OSS Distributions 	assert(new_size > ctx->ctx_buffer_sz);
248*2c2f96dcSApple OSS Distributions 
249*2c2f96dcSApple OSS Distributions 	if (!oslog_is_safe()) {
250*2c2f96dcSApple OSS Distributions 		return false;
251*2c2f96dcSApple OSS Distributions 	}
252*2c2f96dcSApple OSS Distributions 
253*2c2f96dcSApple OSS Distributions 	size_t final_size = new_size;
254*2c2f96dcSApple OSS Distributions 
255*2c2f96dcSApple OSS Distributions 	void *buf = logmem_alloc_locked(ctx->ctx_logmem, &final_size);
256*2c2f96dcSApple OSS Distributions 	if (!buf) {
257*2c2f96dcSApple OSS Distributions 		return false;
258*2c2f96dcSApple OSS Distributions 	}
259*2c2f96dcSApple OSS Distributions 	assert(final_size >= new_size);
260*2c2f96dcSApple OSS Distributions 
261*2c2f96dcSApple OSS Distributions 	// address length header + already stored data
262*2c2f96dcSApple OSS Distributions 	const size_t hdr_size = (uint8_t *)ctx->ctx_hdr - ctx->ctx_buffer;
263*2c2f96dcSApple OSS Distributions 	const size_t copy_size = hdr_size + sizeof(*ctx->ctx_hdr) + ctx->ctx_content_sz;
264*2c2f96dcSApple OSS Distributions 	assert(copy_size <= new_size);
265*2c2f96dcSApple OSS Distributions 	(void) memcpy(buf, ctx->ctx_buffer, copy_size);
266*2c2f96dcSApple OSS Distributions 
267*2c2f96dcSApple OSS Distributions 	if (ctx->ctx_allocated) {
268*2c2f96dcSApple OSS Distributions 		logmem_free_locked(ctx->ctx_logmem, ctx->ctx_buffer, ctx->ctx_buffer_sz);
269*2c2f96dcSApple OSS Distributions 	}
270*2c2f96dcSApple OSS Distributions 
271*2c2f96dcSApple OSS Distributions 	ctx->ctx_buffer = buf;
272*2c2f96dcSApple OSS Distributions 	ctx->ctx_buffer_sz = final_size;
273*2c2f96dcSApple OSS Distributions 	ctx->ctx_content_sz = (uint16_t)(ctx->ctx_buffer_sz - hdr_size - sizeof(*ctx->ctx_hdr));
274*2c2f96dcSApple OSS Distributions 	ctx->ctx_hdr = (os_log_fmt_hdr_t)&ctx->ctx_buffer[hdr_size];
275*2c2f96dcSApple OSS Distributions 	ctx->ctx_allocated = true;
276*2c2f96dcSApple OSS Distributions 
277*2c2f96dcSApple OSS Distributions 	return true;
278*2c2f96dcSApple OSS Distributions }
279*2c2f96dcSApple OSS Distributions 
280*2c2f96dcSApple OSS Distributions static int
log_encode_fmt_arg(void * arg,size_t arg_len,os_log_fmt_cmd_type_t type,os_log_context_t ctx)281*2c2f96dcSApple OSS Distributions log_encode_fmt_arg(void *arg, size_t arg_len, os_log_fmt_cmd_type_t type, os_log_context_t ctx)
282*2c2f96dcSApple OSS Distributions {
283*2c2f96dcSApple OSS Distributions 	int rc = 0;
284*2c2f96dcSApple OSS Distributions 
285*2c2f96dcSApple OSS Distributions 	switch (type) {
286*2c2f96dcSApple OSS Distributions 	case OSLF_CMD_TYPE_COUNT:
287*2c2f96dcSApple OSS Distributions 	case OSLF_CMD_TYPE_SCALAR:
288*2c2f96dcSApple OSS Distributions 		// Scrub kernel pointers.
289*2c2f96dcSApple OSS Distributions 		if (doprnt_hide_pointers && is_kernel_pointer(arg, arg_len)) {
290*2c2f96dcSApple OSS Distributions 			rc = log_add_range_arg(ctx, type, OSLF_CMD_FLAG_PRIVATE, NULL, 0);
291*2c2f96dcSApple OSS Distributions 			ctx->ctx_hdr->hdr_flags |= OSLF_HDR_FLAG_HAS_PRIVATE;
292*2c2f96dcSApple OSS Distributions 		} else {
293*2c2f96dcSApple OSS Distributions 			rc = log_add_arg(ctx, type, arg, arg_len);
294*2c2f96dcSApple OSS Distributions 		}
295*2c2f96dcSApple OSS Distributions 		break;
296*2c2f96dcSApple OSS Distributions 	case OSLF_CMD_TYPE_STRING:
297*2c2f96dcSApple OSS Distributions 		rc = log_add_range_arg(ctx, type, OSLF_CMD_FLAG_PUBLIC, arg, arg_len);
298*2c2f96dcSApple OSS Distributions 		ctx->ctx_hdr->hdr_flags |= OSLF_HDR_FLAG_HAS_NON_SCALAR;
299*2c2f96dcSApple OSS Distributions 		break;
300*2c2f96dcSApple OSS Distributions 	default:
301*2c2f96dcSApple OSS Distributions 		panic("Unsupported log value type");
302*2c2f96dcSApple OSS Distributions 	}
303*2c2f96dcSApple OSS Distributions 
304*2c2f96dcSApple OSS Distributions 	return rc;
305*2c2f96dcSApple OSS Distributions }
306*2c2f96dcSApple OSS Distributions 
307*2c2f96dcSApple OSS Distributions static int
log_encode_fmt(os_log_context_t ctx,const char * format,va_list args)308*2c2f96dcSApple OSS Distributions log_encode_fmt(os_log_context_t ctx, const char *format, va_list args)
309*2c2f96dcSApple OSS Distributions {
310*2c2f96dcSApple OSS Distributions 	const char *position = format;
311*2c2f96dcSApple OSS Distributions 
312*2c2f96dcSApple OSS Distributions 	while ((position = strchr(position, '%'))) {
313*2c2f96dcSApple OSS Distributions 		position++; // Look at character(s) after %.
314*2c2f96dcSApple OSS Distributions 
315*2c2f96dcSApple OSS Distributions 		int type = OST_INT;
316*2c2f96dcSApple OSS Distributions 		boolean_t has_precision = false;
317*2c2f96dcSApple OSS Distributions 		int precision = 0;
318*2c2f96dcSApple OSS Distributions 
319*2c2f96dcSApple OSS Distributions 		for (bool done = false; !done; position++) {
320*2c2f96dcSApple OSS Distributions 			union os_log_fmt_types_u value;
321*2c2f96dcSApple OSS Distributions 			size_t str_length;
322*2c2f96dcSApple OSS Distributions 			int err = 0;
323*2c2f96dcSApple OSS Distributions 
324*2c2f96dcSApple OSS Distributions 			switch (position[0]) {
325*2c2f96dcSApple OSS Distributions 			case '%':
326*2c2f96dcSApple OSS Distributions 				// %% prints % character
327*2c2f96dcSApple OSS Distributions 				done = true;
328*2c2f96dcSApple OSS Distributions 				break;
329*2c2f96dcSApple OSS Distributions 
330*2c2f96dcSApple OSS Distributions 			/* type of types or other */
331*2c2f96dcSApple OSS Distributions 			case 'l': // longer
332*2c2f96dcSApple OSS Distributions 				type++;
333*2c2f96dcSApple OSS Distributions 				break;
334*2c2f96dcSApple OSS Distributions 
335*2c2f96dcSApple OSS Distributions 			case 'h': // shorter
336*2c2f96dcSApple OSS Distributions 				type--;
337*2c2f96dcSApple OSS Distributions 				break;
338*2c2f96dcSApple OSS Distributions 
339*2c2f96dcSApple OSS Distributions 			case 'z':
340*2c2f96dcSApple OSS Distributions 				type = OST_SIZE;
341*2c2f96dcSApple OSS Distributions 				break;
342*2c2f96dcSApple OSS Distributions 
343*2c2f96dcSApple OSS Distributions 			case 'j':
344*2c2f96dcSApple OSS Distributions 				type = OST_INTMAX;
345*2c2f96dcSApple OSS Distributions 				break;
346*2c2f96dcSApple OSS Distributions 
347*2c2f96dcSApple OSS Distributions 			case 't':
348*2c2f96dcSApple OSS Distributions 				type = OST_PTRDIFF;
349*2c2f96dcSApple OSS Distributions 				break;
350*2c2f96dcSApple OSS Distributions 
351*2c2f96dcSApple OSS Distributions 			case 'q':
352*2c2f96dcSApple OSS Distributions 				type = OST_LONGLONG;
353*2c2f96dcSApple OSS Distributions 				break;
354*2c2f96dcSApple OSS Distributions 
355*2c2f96dcSApple OSS Distributions 			case '.': // precision
356*2c2f96dcSApple OSS Distributions 				if (position[1] == '*') {
357*2c2f96dcSApple OSS Distributions 					// Dynamic precision, argument holds actual value.
358*2c2f96dcSApple OSS Distributions 					precision = va_arg(args, int);
359*2c2f96dcSApple OSS Distributions 					position++;
360*2c2f96dcSApple OSS Distributions 				} else {
361*2c2f96dcSApple OSS Distributions 					// Static precision, the value follows in the fmt.
362*2c2f96dcSApple OSS Distributions 					precision = 0;
363*2c2f96dcSApple OSS Distributions 					while (is_digit(position[1])) {
364*2c2f96dcSApple OSS Distributions 						if (precision < LOG_FMT_MAX_PRECISION) {
365*2c2f96dcSApple OSS Distributions 							precision = 10 * precision + (position[1] - '0');
366*2c2f96dcSApple OSS Distributions 						}
367*2c2f96dcSApple OSS Distributions 						position++;
368*2c2f96dcSApple OSS Distributions 					}
369*2c2f96dcSApple OSS Distributions 					precision = MIN(precision, LOG_FMT_MAX_PRECISION);
370*2c2f96dcSApple OSS Distributions 				}
371*2c2f96dcSApple OSS Distributions 				err = log_encode_fmt_arg(&precision, sizeof(precision), OSLF_CMD_TYPE_COUNT, ctx);
372*2c2f96dcSApple OSS Distributions 				// A negative precision is treated as though it were missing.
373*2c2f96dcSApple OSS Distributions 				if (precision >= 0) {
374*2c2f96dcSApple OSS Distributions 					has_precision = true;
375*2c2f96dcSApple OSS Distributions 				}
376*2c2f96dcSApple OSS Distributions 				break;
377*2c2f96dcSApple OSS Distributions 
378*2c2f96dcSApple OSS Distributions 			case '-': // left-align
379*2c2f96dcSApple OSS Distributions 			case '+': // force sign
380*2c2f96dcSApple OSS Distributions 			case ' ': // prefix non-negative with space
381*2c2f96dcSApple OSS Distributions 			case '#': // alternate
382*2c2f96dcSApple OSS Distributions 			case '\'': // group by thousands
383*2c2f96dcSApple OSS Distributions 				break;
384*2c2f96dcSApple OSS Distributions 
385*2c2f96dcSApple OSS Distributions 			/* fixed types */
386*2c2f96dcSApple OSS Distributions 			case 'd': // integer
387*2c2f96dcSApple OSS Distributions 			case 'i': // integer
388*2c2f96dcSApple OSS Distributions 			case 'o': // octal
389*2c2f96dcSApple OSS Distributions 			case 'u': // unsigned
390*2c2f96dcSApple OSS Distributions 			case 'x': // hex
391*2c2f96dcSApple OSS Distributions 			case 'X': // upper-hex
392*2c2f96dcSApple OSS Distributions 				switch (type) {
393*2c2f96dcSApple OSS Distributions 				case OST_CHAR:
394*2c2f96dcSApple OSS Distributions 					value.ch = (char) va_arg(args, int);
395*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.ch, sizeof(value.ch), OSLF_CMD_TYPE_SCALAR, ctx);
396*2c2f96dcSApple OSS Distributions 					break;
397*2c2f96dcSApple OSS Distributions 
398*2c2f96dcSApple OSS Distributions 				case OST_SHORT:
399*2c2f96dcSApple OSS Distributions 					value.s = (short) va_arg(args, int);
400*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.s, sizeof(value.s), OSLF_CMD_TYPE_SCALAR, ctx);
401*2c2f96dcSApple OSS Distributions 					break;
402*2c2f96dcSApple OSS Distributions 
403*2c2f96dcSApple OSS Distributions 				case OST_INT:
404*2c2f96dcSApple OSS Distributions 					value.i = va_arg(args, int);
405*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.i, sizeof(value.i), OSLF_CMD_TYPE_SCALAR, ctx);
406*2c2f96dcSApple OSS Distributions 					break;
407*2c2f96dcSApple OSS Distributions 
408*2c2f96dcSApple OSS Distributions 				case OST_LONG:
409*2c2f96dcSApple OSS Distributions 					value.l = va_arg(args, long);
410*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.l, sizeof(value.l), OSLF_CMD_TYPE_SCALAR, ctx);
411*2c2f96dcSApple OSS Distributions 					break;
412*2c2f96dcSApple OSS Distributions 
413*2c2f96dcSApple OSS Distributions 				case OST_LONGLONG:
414*2c2f96dcSApple OSS Distributions 					value.ll = va_arg(args, long long);
415*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.ll, sizeof(value.ll), OSLF_CMD_TYPE_SCALAR, ctx);
416*2c2f96dcSApple OSS Distributions 					break;
417*2c2f96dcSApple OSS Distributions 
418*2c2f96dcSApple OSS Distributions 				case OST_SIZE:
419*2c2f96dcSApple OSS Distributions 					value.z = va_arg(args, size_t);
420*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.z, sizeof(value.z), OSLF_CMD_TYPE_SCALAR, ctx);
421*2c2f96dcSApple OSS Distributions 					break;
422*2c2f96dcSApple OSS Distributions 
423*2c2f96dcSApple OSS Distributions 				case OST_INTMAX:
424*2c2f96dcSApple OSS Distributions 					value.im = va_arg(args, intmax_t);
425*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.im, sizeof(value.im), OSLF_CMD_TYPE_SCALAR, ctx);
426*2c2f96dcSApple OSS Distributions 					break;
427*2c2f96dcSApple OSS Distributions 
428*2c2f96dcSApple OSS Distributions 				case OST_PTRDIFF:
429*2c2f96dcSApple OSS Distributions 					value.pd = va_arg(args, ptrdiff_t);
430*2c2f96dcSApple OSS Distributions 					err = log_encode_fmt_arg(&value.pd, sizeof(value.pd), OSLF_CMD_TYPE_SCALAR, ctx);
431*2c2f96dcSApple OSS Distributions 					break;
432*2c2f96dcSApple OSS Distributions 
433*2c2f96dcSApple OSS Distributions 				default:
434*2c2f96dcSApple OSS Distributions 					return EINVAL;
435*2c2f96dcSApple OSS Distributions 				}
436*2c2f96dcSApple OSS Distributions 				done = true;
437*2c2f96dcSApple OSS Distributions 				break;
438*2c2f96dcSApple OSS Distributions 
439*2c2f96dcSApple OSS Distributions 			case 'p': // pointer
440*2c2f96dcSApple OSS Distributions 				value.p = va_arg(args, void *);
441*2c2f96dcSApple OSS Distributions 				err = log_encode_fmt_arg(&value.p, sizeof(value.p), OSLF_CMD_TYPE_SCALAR, ctx);
442*2c2f96dcSApple OSS Distributions 				done = true;
443*2c2f96dcSApple OSS Distributions 				break;
444*2c2f96dcSApple OSS Distributions 
445*2c2f96dcSApple OSS Distributions 			case 'c': // char
446*2c2f96dcSApple OSS Distributions 				value.ch = (char) va_arg(args, int);
447*2c2f96dcSApple OSS Distributions 				err = log_encode_fmt_arg(&value.ch, sizeof(value.ch), OSLF_CMD_TYPE_SCALAR, ctx);
448*2c2f96dcSApple OSS Distributions 				done = true;
449*2c2f96dcSApple OSS Distributions 				break;
450*2c2f96dcSApple OSS Distributions 
451*2c2f96dcSApple OSS Distributions 			case 's': // string
452*2c2f96dcSApple OSS Distributions 				value.pch = va_arg(args, char *);
453*2c2f96dcSApple OSS Distributions 				if (!value.pch) {
454*2c2f96dcSApple OSS Distributions 					str_length = 0;
455*2c2f96dcSApple OSS Distributions 				} else if (has_precision) {
456*2c2f96dcSApple OSS Distributions 					assert(precision >= 0);
457*2c2f96dcSApple OSS Distributions 					str_length = strnlen(value.pch, precision);
458*2c2f96dcSApple OSS Distributions 				} else {
459*2c2f96dcSApple OSS Distributions 					str_length = strlen(value.pch) + 1;
460*2c2f96dcSApple OSS Distributions 				}
461*2c2f96dcSApple OSS Distributions 				err = log_encode_fmt_arg(value.pch, str_length, OSLF_CMD_TYPE_STRING, ctx);
462*2c2f96dcSApple OSS Distributions 				done = true;
463*2c2f96dcSApple OSS Distributions 				break;
464*2c2f96dcSApple OSS Distributions 
465*2c2f96dcSApple OSS Distributions 			case 'm':
466*2c2f96dcSApple OSS Distributions 				value.i = 0; // Does %m make sense in the kernel?
467*2c2f96dcSApple OSS Distributions 				err = log_encode_fmt_arg(&value.i, sizeof(value.i), OSLF_CMD_TYPE_SCALAR, ctx);
468*2c2f96dcSApple OSS Distributions 				done = true;
469*2c2f96dcSApple OSS Distributions 				break;
470*2c2f96dcSApple OSS Distributions 
471*2c2f96dcSApple OSS Distributions 			case '0' ... '9':
472*2c2f96dcSApple OSS Distributions 				// Skipping field width, libtrace takes care of it.
473*2c2f96dcSApple OSS Distributions 				break;
474*2c2f96dcSApple OSS Distributions 
475*2c2f96dcSApple OSS Distributions 			default:
476*2c2f96dcSApple OSS Distributions 				return EINVAL;
477*2c2f96dcSApple OSS Distributions 			}
478*2c2f96dcSApple OSS Distributions 
479*2c2f96dcSApple OSS Distributions 			if (slowpath(err)) {
480*2c2f96dcSApple OSS Distributions 				return err;
481*2c2f96dcSApple OSS Distributions 			}
482*2c2f96dcSApple OSS Distributions 		}
483*2c2f96dcSApple OSS Distributions 	}
484*2c2f96dcSApple OSS Distributions 
485*2c2f96dcSApple OSS Distributions 	return 0;
486*2c2f96dcSApple OSS Distributions }
487*2c2f96dcSApple OSS Distributions 
488*2c2f96dcSApple OSS Distributions OS_ALWAYS_INLINE
489*2c2f96dcSApple OSS Distributions static inline void
tracepoint_buf_add(tracepoint_buf_t * tp,const void * data,size_t size)490*2c2f96dcSApple OSS Distributions tracepoint_buf_add(tracepoint_buf_t *tp, const void *data, size_t size)
491*2c2f96dcSApple OSS Distributions {
492*2c2f96dcSApple OSS Distributions 	assert((tp->tp_size + size) <= TRACEPOINT_BUF_MAX_SIZE);
493*2c2f96dcSApple OSS Distributions 	memcpy(&tp->tp_buf[tp->tp_size], data, size);
494*2c2f96dcSApple OSS Distributions 	tp->tp_size += size;
495*2c2f96dcSApple OSS Distributions }
496*2c2f96dcSApple OSS Distributions 
497*2c2f96dcSApple OSS Distributions static void
tracepoint_buf_location(tracepoint_buf_t * tpb,uintptr_t loc,size_t loc_size)498*2c2f96dcSApple OSS Distributions tracepoint_buf_location(tracepoint_buf_t *tpb, uintptr_t loc, size_t loc_size)
499*2c2f96dcSApple OSS Distributions {
500*2c2f96dcSApple OSS Distributions 	if (loc_size == sizeof(uintptr_t)) {
501*2c2f96dcSApple OSS Distributions #if __LP64__
502*2c2f96dcSApple OSS Distributions 		loc_size = 6; // 48 bits are enough
503*2c2f96dcSApple OSS Distributions #endif
504*2c2f96dcSApple OSS Distributions 		tracepoint_buf_add(tpb, (uintptr_t[]){ loc }, loc_size);
505*2c2f96dcSApple OSS Distributions 	} else {
506*2c2f96dcSApple OSS Distributions 		assert(loc_size == sizeof(uint32_t));
507*2c2f96dcSApple OSS Distributions 		tracepoint_buf_add(tpb, (uint32_t[]){ (uint32_t)loc }, loc_size);
508*2c2f96dcSApple OSS Distributions 	}
509*2c2f96dcSApple OSS Distributions }
510*2c2f96dcSApple OSS Distributions 
511*2c2f96dcSApple OSS Distributions static void
os_log_context_prepare_header(os_log_context_t ctx,size_t hdr_size)512*2c2f96dcSApple OSS Distributions os_log_context_prepare_header(os_log_context_t ctx, size_t hdr_size)
513*2c2f96dcSApple OSS Distributions {
514*2c2f96dcSApple OSS Distributions 	assert(hdr_size > 0 && hdr_size <= TRACEPOINT_BUF_MAX_SIZE);
515*2c2f96dcSApple OSS Distributions 	ctx->ctx_hdr = (os_log_fmt_hdr_t)&ctx->ctx_buffer[hdr_size];
516*2c2f96dcSApple OSS Distributions 	bzero(ctx->ctx_hdr, sizeof(*ctx->ctx_hdr));
517*2c2f96dcSApple OSS Distributions 	ctx->ctx_content_sz = (uint16_t)(ctx->ctx_buffer_sz - hdr_size - sizeof(*ctx->ctx_hdr));
518*2c2f96dcSApple OSS Distributions }
519*2c2f96dcSApple OSS Distributions 
520*2c2f96dcSApple OSS Distributions /*
521*2c2f96dcSApple OSS Distributions  * Encodes argument (meta)data into a format consumed by libtrace. Stores
522*2c2f96dcSApple OSS Distributions  * metadada for all arguments first. Metadata also include scalar argument
523*2c2f96dcSApple OSS Distributions  * values. Second step saves data which are encoded separately from respective
524*2c2f96dcSApple OSS Distributions  * metadata (like strings).
525*2c2f96dcSApple OSS Distributions  */
526*2c2f96dcSApple OSS Distributions bool
os_log_context_encode(os_log_context_t ctx,const char * fmt,va_list args,uintptr_t loc,size_t loc_size,uint16_t subsystem_id)527*2c2f96dcSApple OSS Distributions os_log_context_encode(os_log_context_t ctx, const char *fmt, va_list args,
528*2c2f96dcSApple OSS Distributions     uintptr_t loc, size_t loc_size, uint16_t subsystem_id)
529*2c2f96dcSApple OSS Distributions {
530*2c2f96dcSApple OSS Distributions 	tracepoint_buf_t tpb = {
531*2c2f96dcSApple OSS Distributions 		.tp_buf     = ctx->ctx_buffer,
532*2c2f96dcSApple OSS Distributions 		.tp_size    = 0
533*2c2f96dcSApple OSS Distributions 	};
534*2c2f96dcSApple OSS Distributions 
535*2c2f96dcSApple OSS Distributions 	tracepoint_buf_location(&tpb, loc, loc_size);
536*2c2f96dcSApple OSS Distributions 	if (os_log_subsystem_id_valid(subsystem_id)) {
537*2c2f96dcSApple OSS Distributions 		tracepoint_buf_add(&tpb, &subsystem_id, sizeof(subsystem_id));
538*2c2f96dcSApple OSS Distributions 	}
539*2c2f96dcSApple OSS Distributions 	os_log_context_prepare_header(ctx, tpb.tp_size);
540*2c2f96dcSApple OSS Distributions 
541*2c2f96dcSApple OSS Distributions 	va_list args_copy;
542*2c2f96dcSApple OSS Distributions 	va_copy(args_copy, args);
543*2c2f96dcSApple OSS Distributions 
544*2c2f96dcSApple OSS Distributions 	int rc = log_encode_fmt(ctx, fmt, args);
545*2c2f96dcSApple OSS Distributions 
546*2c2f96dcSApple OSS Distributions 	va_end(args_copy);
547*2c2f96dcSApple OSS Distributions 
548*2c2f96dcSApple OSS Distributions 	switch (rc) {
549*2c2f96dcSApple OSS Distributions 	case EINVAL:
550*2c2f96dcSApple OSS Distributions 		// Bogus/Unsupported fmt string
551*2c2f96dcSApple OSS Distributions 		counter_inc(&oslog_p_fmt_invalid_msgcount);
552*2c2f96dcSApple OSS Distributions 		return false;
553*2c2f96dcSApple OSS Distributions 	case ENOMEM:
554*2c2f96dcSApple OSS Distributions 		/*
555*2c2f96dcSApple OSS Distributions 		 * The fmt contains unreasonable number of arguments (> 32) and
556*2c2f96dcSApple OSS Distributions 		 * we ran out of space. We could call log_expand()
557*2c2f96dcSApple OSS Distributions 		 * here and retry. However, using such formatting strings rather
558*2c2f96dcSApple OSS Distributions 		 * seem like a misuse of the logging system, hence error.
559*2c2f96dcSApple OSS Distributions 		 */
560*2c2f96dcSApple OSS Distributions 		counter_inc(&oslog_p_fmt_max_args_msgcount);
561*2c2f96dcSApple OSS Distributions 		return false;
562*2c2f96dcSApple OSS Distributions 	case 0:
563*2c2f96dcSApple OSS Distributions 		break;
564*2c2f96dcSApple OSS Distributions 	default:
565*2c2f96dcSApple OSS Distributions 		panic("unhandled return value");
566*2c2f96dcSApple OSS Distributions 	}
567*2c2f96dcSApple OSS Distributions 
568*2c2f96dcSApple OSS Distributions 	if (ctx->ctx_pubdata_sz == 0) {
569*2c2f96dcSApple OSS Distributions 		goto finish;
570*2c2f96dcSApple OSS Distributions 	}
571*2c2f96dcSApple OSS Distributions 
572*2c2f96dcSApple OSS Distributions 	/*
573*2c2f96dcSApple OSS Distributions 	 * Logmem may not have been set up yet when logging very early during
574*2c2f96dcSApple OSS Distributions 	 * the boot. Be sure to check its state.
575*2c2f96dcSApple OSS Distributions 	 */
576*2c2f96dcSApple OSS Distributions 	if (!log_fits(ctx, ctx->ctx_pubdata_sz) && logmem_ready(ctx->ctx_logmem)) {
577*2c2f96dcSApple OSS Distributions 		size_t space_needed = log_context_cursor(ctx) + ctx->ctx_pubdata_sz - ctx->ctx_buffer;
578*2c2f96dcSApple OSS Distributions 		space_needed = MIN(space_needed, logmem_max_size(ctx->ctx_logmem));
579*2c2f96dcSApple OSS Distributions 		(void) log_expand(ctx, space_needed);
580*2c2f96dcSApple OSS Distributions 	}
581*2c2f96dcSApple OSS Distributions 
582*2c2f96dcSApple OSS Distributions 	log_encode_public_data(ctx);
583*2c2f96dcSApple OSS Distributions 
584*2c2f96dcSApple OSS Distributions 	if (ctx->ctx_truncated) {
585*2c2f96dcSApple OSS Distributions 		counter_inc(&oslog_p_truncated_msgcount);
586*2c2f96dcSApple OSS Distributions 	}
587*2c2f96dcSApple OSS Distributions finish:
588*2c2f96dcSApple OSS Distributions 	ctx->ctx_content_sz = (uint16_t)(log_context_cursor(ctx) - ctx->ctx_buffer);
589*2c2f96dcSApple OSS Distributions 	ctx->ctx_content_off = 0;
590*2c2f96dcSApple OSS Distributions 	return true;
591*2c2f96dcSApple OSS Distributions }
592*2c2f96dcSApple OSS Distributions 
593*2c2f96dcSApple OSS Distributions void
os_log_context_init(os_log_context_t ctx,logmem_t * logmem,uint8_t * buffer,size_t buffer_sz)594*2c2f96dcSApple OSS Distributions os_log_context_init(os_log_context_t ctx, logmem_t *logmem, uint8_t *buffer, size_t buffer_sz)
595*2c2f96dcSApple OSS Distributions {
596*2c2f96dcSApple OSS Distributions 	assert(logmem);
597*2c2f96dcSApple OSS Distributions 	assert(buffer);
598*2c2f96dcSApple OSS Distributions 	assert(buffer_sz > 0);
599*2c2f96dcSApple OSS Distributions 
600*2c2f96dcSApple OSS Distributions 	bzero(ctx, sizeof(*ctx));
601*2c2f96dcSApple OSS Distributions 	ctx->ctx_logmem = logmem;
602*2c2f96dcSApple OSS Distributions 	ctx->ctx_buffer = buffer;
603*2c2f96dcSApple OSS Distributions 	ctx->ctx_buffer_sz = buffer_sz;
604*2c2f96dcSApple OSS Distributions }
605*2c2f96dcSApple OSS Distributions 
606*2c2f96dcSApple OSS Distributions void
os_log_context_free(os_log_context_t ctx)607*2c2f96dcSApple OSS Distributions os_log_context_free(os_log_context_t ctx)
608*2c2f96dcSApple OSS Distributions {
609*2c2f96dcSApple OSS Distributions 	if (ctx->ctx_allocated) {
610*2c2f96dcSApple OSS Distributions 		logmem_free_locked(ctx->ctx_logmem, ctx->ctx_buffer, ctx->ctx_buffer_sz);
611*2c2f96dcSApple OSS Distributions 	}
612*2c2f96dcSApple OSS Distributions }
613