X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d9a64523371fa019c4575bb400cbbc3a50ac9903..eb6b6ca394357805f2bdba989abae309f718b4d8:/libkern/os/log_encode.h?ds=sidebyside diff --git a/libkern/os/log_encode.h b/libkern/os/log_encode.h index d214bab21..4591be6dc 100644 --- a/libkern/os/log_encode.h +++ b/libkern/os/log_encode.h @@ -40,105 +40,105 @@ extern boolean_t doprnt_hide_pointers; static bool _encode_data(os_log_buffer_value_t content, const void *arg, uint16_t arg_len, os_log_buffer_context_t context) { - struct os_log_arginfo_s arginfo; - void *databuf; - - if (content->flags & OS_LOG_CONTENT_FLAG_PRIVATE) { - databuf = context->privdata + context->privdata_off; - arginfo.length = MIN(arg_len, (context->privdata_sz - context->privdata_off)); - arginfo.offset = context->privdata_off; - } else { - databuf = context->pubdata + context->pubdata_off; - arginfo.length = MIN(arg_len, (context->pubdata_sz - context->pubdata_off)); - arginfo.offset = context->pubdata_off; - } - - if (context->arg_content_sz > 0) { - arginfo.length = MIN(context->arg_content_sz, arginfo.length); - } - - memcpy(content->value, &arginfo, sizeof(arginfo)); - content->size = sizeof(arginfo); - - if (arginfo.length) { - if (content->type == OS_LOG_BUFFER_VALUE_TYPE_STRING + struct os_log_arginfo_s arginfo; + void *databuf; + + if (content->flags & OS_LOG_CONTENT_FLAG_PRIVATE) { + databuf = context->privdata + context->privdata_off; + arginfo.length = MIN(arg_len, (context->privdata_sz - context->privdata_off)); + arginfo.offset = context->privdata_off; + } else { + databuf = context->pubdata + context->pubdata_off; + arginfo.length = MIN(arg_len, (context->pubdata_sz - context->pubdata_off)); + arginfo.offset = context->pubdata_off; + } + + if (context->arg_content_sz > 0) { + arginfo.length = MIN(context->arg_content_sz, arginfo.length); + } + + memcpy(content->value, &arginfo, sizeof(arginfo)); + content->size = sizeof(arginfo); + + if (arginfo.length) { + if (content->type == OS_LOG_BUFFER_VALUE_TYPE_STRING #ifndef KERNEL - || content->type == OS_LOG_BUFFER_VALUE_TYPE_OBJECT + || content->type == OS_LOG_BUFFER_VALUE_TYPE_OBJECT #endif - ) { - strlcpy(databuf, arg, arginfo.length); - } else { - memcpy(databuf, arg, arginfo.length); - } - } - - if (content->flags & OS_LOG_CONTENT_FLAG_PRIVATE) { - context->privdata_off += arginfo.length; - } else { - context->pubdata_off += arginfo.length; - } - - context->content_off += sizeof(*content) + content->size; - context->arg_content_sz = 0; - - return true; + ) { + strlcpy(databuf, arg, arginfo.length); + } else { + memcpy(databuf, arg, arginfo.length); + } + } + + if (content->flags & OS_LOG_CONTENT_FLAG_PRIVATE) { + context->privdata_off += arginfo.length; + } else { + context->pubdata_off += arginfo.length; + } + + context->content_off += sizeof(*content) + content->size; + context->arg_content_sz = 0; + + return true; } #ifndef KERNEL static void _os_log_parse_annotated(char *annotated, const char **visibility, const char **library, const char **type) { - char *values[3] = { NULL }; - int cnt = 0; - int idx = 0; - - for (; cnt < 3;) { - char *token = strsep(&annotated, ", {}"); - if (token == NULL) { - break; - } - - if (*token == '\0') { - continue; - } - - values[cnt++] = token; - } - - if ((cnt > 0) && (!strcmp(values[0], "public") || !strcmp(values[0], "private"))) { - if (visibility != NULL) { - (*visibility) = values[0]; - } - - idx++; - } - - if (idx < cnt && (library != NULL) && (type != NULL)) { - char *decoder = values[idx]; - - for (cnt = 0; cnt < 3; ) { - char *token = strsep(&decoder, ": {}"); - if (token == NULL) { - break; - } - - if (*token == '\0') { - continue; - } - - values[cnt++] = token; - } - - if (cnt == 2) { - (*library) = values[0]; - (*type) = values[1]; - } - - if (cnt == 1) { - (*library) = "builtin"; - (*type) = values[0]; - } - } + char *values[3] = { NULL }; + int cnt = 0; + int idx = 0; + + for (; cnt < 3;) { + char *token = strsep(&annotated, ", {}"); + if (token == NULL) { + break; + } + + if (*token == '\0') { + continue; + } + + values[cnt++] = token; + } + + if ((cnt > 0) && (!strcmp(values[0], "public") || !strcmp(values[0], "private"))) { + if (visibility != NULL) { + (*visibility) = values[0]; + } + + idx++; + } + + if (idx < cnt && (library != NULL) && (type != NULL)) { + char *decoder = values[idx]; + + for (cnt = 0; cnt < 3;) { + char *token = strsep(&decoder, ": {}"); + if (token == NULL) { + break; + } + + if (*token == '\0') { + continue; + } + + values[cnt++] = token; + } + + if (cnt == 2) { + (*library) = values[0]; + (*type) = values[1]; + } + + if (cnt == 1) { + (*library) = "builtin"; + (*type) = values[0]; + } + } } #endif /* !KERNEL */ @@ -146,384 +146,384 @@ OS_ALWAYS_INLINE static inline bool _os_log_encode_arg(void *arg, uint16_t arg_len, os_log_value_type_t ctype, bool is_private, os_log_buffer_context_t context) { - os_log_buffer_value_t content = (os_log_buffer_value_t) &context->buffer->content[context->content_off]; - size_t content_sz = sizeof(*content) + arg_len; - char tempString[OS_LOG_BUFFER_MAX_SIZE] = {}; + os_log_buffer_value_t content = (os_log_buffer_value_t) &context->buffer->content[context->content_off]; + size_t content_sz = sizeof(*content) + arg_len; + char tempString[OS_LOG_BUFFER_MAX_SIZE] = {}; #ifndef KERNEL - bool obj_private = true; + bool obj_private = true; #endif #ifdef KERNEL - /* scrub kernel pointers */ - if (doprnt_hide_pointers && - ctype == OS_LOG_BUFFER_VALUE_TYPE_SCALAR && - arg_len >= sizeof(void *)) { - unsigned long long value = 0; - memcpy(&value, arg, arg_len); + /* scrub kernel pointers */ + if (doprnt_hide_pointers && + ctype == OS_LOG_BUFFER_VALUE_TYPE_SCALAR && + arg_len >= sizeof(void *)) { + unsigned long long value = 0; + memcpy(&value, arg, arg_len); #if __has_feature(ptrauth_calls) - /** - * Strip out the pointer authentication code before - * checking whether the pointer is a kernel address. - */ - value = (unsigned long long)VM_KERNEL_STRIP_PTR(value); + /** + * Strip out the pointer authentication code before + * checking whether the pointer is a kernel address. + */ + value = (unsigned long long)VM_KERNEL_STRIP_PTR(value); #endif /* __has_feature(ptrauth_calls) */ - if (value >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && value <= VM_MAX_KERNEL_ADDRESS) { - is_private = true; - bzero(arg, arg_len); - } - } + if (value >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && value <= VM_MAX_KERNEL_ADDRESS) { + is_private = true; + bzero(arg, arg_len); + } + } #endif - content->type = ctype; - content->flags = (is_private ? OS_LOG_CONTENT_FLAG_PRIVATE : 0); - + content->type = ctype; + content->flags = (is_private ? OS_LOG_CONTENT_FLAG_PRIVATE : 0); + #ifndef KERNEL - if (context->annotated != NULL) { - const char *visibility = NULL; - - _os_log_parse_annotated(context->annotated, &visibility, NULL, NULL); - if (visibility) { - if (!strcasecmp(visibility, "private")) { - content->flags |= OS_LOG_CONTENT_FLAG_PRIVATE; - } else if (!strcasecmp(visibility, "public")) { - content->flags &= ~OS_LOG_CONTENT_FLAG_PRIVATE; - } - } - - context->annotated = NULL; - } + if (context->annotated != NULL) { + const char *visibility = NULL; + + _os_log_parse_annotated(context->annotated, &visibility, NULL, NULL); + if (visibility) { + if (!strcasecmp(visibility, "private")) { + content->flags |= OS_LOG_CONTENT_FLAG_PRIVATE; + } else if (!strcasecmp(visibility, "public")) { + content->flags &= ~OS_LOG_CONTENT_FLAG_PRIVATE; + } + } + + context->annotated = NULL; + } #endif /* !KERNEL */ - - switch (ctype) { - case OS_LOG_BUFFER_VALUE_TYPE_COUNT: - case OS_LOG_BUFFER_VALUE_TYPE_SCALAR: - if (is_private) { - _encode_data(content, tempString, strlen(tempString) + 1, context); - } else { - if ((context->content_off + content_sz) > context->content_sz) { - return false; - } - - memcpy(content->value, arg, arg_len); - content->size = arg_len; - context->content_off += content_sz; - } - break; - - case OS_LOG_BUFFER_VALUE_TYPE_STRING: - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - if (_os_log_string_is_public(arg)) { - content->flags &= ~OS_LOG_CONTENT_FLAG_PRIVATE; - } - - _encode_data(content, arg, arg_len, context); - break; - + + switch (ctype) { + case OS_LOG_BUFFER_VALUE_TYPE_COUNT: + case OS_LOG_BUFFER_VALUE_TYPE_SCALAR: + if (is_private) { + _encode_data(content, tempString, strlen(tempString) + 1, context); + } else { + if ((context->content_off + content_sz) > context->content_sz) { + return false; + } + + memcpy(content->value, arg, arg_len); + content->size = arg_len; + context->content_off += content_sz; + } + break; + + case OS_LOG_BUFFER_VALUE_TYPE_STRING: + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + if (_os_log_string_is_public(arg)) { + content->flags &= ~OS_LOG_CONTENT_FLAG_PRIVATE; + } + + _encode_data(content, arg, arg_len, context); + break; + #ifndef KERNEL - case OS_LOG_BUFFER_VALUE_TYPE_POINTER: - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - _encode_data(content, arg, arg_len, context); - break; - - case OS_LOG_BUFFER_VALUE_TYPE_OBJECT: - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - if (!_NSCF2data(arg, tempString, sizeof(tempString), &obj_private)) { - tempString[0] = '\0'; - } - - if (!obj_private) { - content->flags &= ~OS_LOG_CONTENT_FLAG_PRIVATE; - } - - _encode_data(content, tempString, strlen(tempString) + 1, context); - break; + case OS_LOG_BUFFER_VALUE_TYPE_POINTER: + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + _encode_data(content, arg, arg_len, context); + break; + + case OS_LOG_BUFFER_VALUE_TYPE_OBJECT: + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + if (!_NSCF2data(arg, tempString, sizeof(tempString), &obj_private)) { + tempString[0] = '\0'; + } + + if (!obj_private) { + content->flags &= ~OS_LOG_CONTENT_FLAG_PRIVATE; + } + + _encode_data(content, tempString, strlen(tempString) + 1, context); + break; #endif /* !KERNEL */ - } - - if (content->flags & OS_LOG_CONTENT_FLAG_PRIVATE) { - context->buffer->flags |= OS_LOG_BUFFER_HAS_PRIVATE; - } - - context->arg_idx++; - - return true; + } + + if (content->flags & OS_LOG_CONTENT_FLAG_PRIVATE) { + context->buffer->flags |= OS_LOG_BUFFER_HAS_PRIVATE; + } + + context->arg_idx++; + + return true; } static bool _os_log_encode(const char *format, va_list args, int saved_errno, os_log_buffer_context_t context) { - const char *percent = strchr(format, '%'); + const char *percent = strchr(format, '%'); #ifndef KERNEL - char annotated[256]; + char annotated[256]; #endif - - while (percent != NULL) { - ++percent; - if (percent[0] != '%') { - struct os_log_format_value_s value; - int type = OST_INT; + + while (percent != NULL) { + ++percent; + if (percent[0] != '%') { + struct os_log_format_value_s value; + int type = OST_INT; #ifndef KERNEL - bool long_double = false; + bool long_double = false; #endif - int prec = 0; - char ch; - - for (bool done = false; !done; percent++) { - switch (ch = percent[0]) { - /* type of types or other */ - case 'l': // longer - type++; - break; - - case 'h': // shorter - type--; - break; - - case 'z': - type = OST_SIZE; - break; - - case 'j': - type = OST_INTMAX; - break; - - case 't': - type = OST_PTRDIFF; - break; - - case '.': // precision - if ((percent[1]) == '*') { - prec = va_arg(args, int); - _os_log_encode_arg(&prec, sizeof(prec), OS_LOG_BUFFER_VALUE_TYPE_COUNT, false, context); - percent++; - continue; - } else { - // we have to read the precision and do the right thing - const char *fmt = percent + 1; - prec = 0; - while (isdigit(ch = *fmt++)) { - prec = 10 * prec + (ch - '0'); - } - - if (prec > 1024) { - prec = 1024; - } - - _os_log_encode_arg(&prec, sizeof(prec), OS_LOG_BUFFER_VALUE_TYPE_COUNT, false, context); - } - break; - - case '-': // left-align - case '+': // force sign - case ' ': // prefix non-negative with space - case '#': // alternate - case '\'': // group by thousands - break; - - /* fixed types */ - case 'd': // integer - case 'i': // integer - case 'o': // octal - case 'u': // unsigned - case 'x': // hex - case 'X': // upper-hex - switch (type) { - case OST_CHAR: - value.type.ch = va_arg(args, int); - _os_log_encode_arg(&value.type.ch, sizeof(value.type.ch), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_SHORT: - value.type.s = va_arg(args, int); - _os_log_encode_arg(&value.type.s, sizeof(value.type.s), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_INT: - value.type.i = va_arg(args, int); - _os_log_encode_arg(&value.type.i, sizeof(value.type.i), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_LONG: - value.type.l = va_arg(args, long); - _os_log_encode_arg(&value.type.l, sizeof(value.type.l), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_LONGLONG: - value.type.ll = va_arg(args, long long); - _os_log_encode_arg(&value.type.ll, sizeof(value.type.ll), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_SIZE: - value.type.z = va_arg(args, size_t); - _os_log_encode_arg(&value.type.z, sizeof(value.type.z), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_INTMAX: - value.type.im = va_arg(args, intmax_t); - _os_log_encode_arg(&value.type.im, sizeof(value.type.im), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - case OST_PTRDIFF: - value.type.pd = va_arg(args, ptrdiff_t); - _os_log_encode_arg(&value.type.pd, sizeof(value.type.pd), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - break; - - default: - return false; - } - done = true; - break; - + int prec = 0; + char ch; + + for (bool done = false; !done; percent++) { + switch (ch = percent[0]) { + /* type of types or other */ + case 'l': // longer + type++; + break; + + case 'h': // shorter + type--; + break; + + case 'z': + type = OST_SIZE; + break; + + case 'j': + type = OST_INTMAX; + break; + + case 't': + type = OST_PTRDIFF; + break; + + case '.': // precision + if ((percent[1]) == '*') { + prec = va_arg(args, int); + _os_log_encode_arg(&prec, sizeof(prec), OS_LOG_BUFFER_VALUE_TYPE_COUNT, false, context); + percent++; + continue; + } else { + // we have to read the precision and do the right thing + const char *fmt = percent + 1; + prec = 0; + while (isdigit(ch = *fmt++)) { + prec = 10 * prec + (ch - '0'); + } + + if (prec > 1024) { + prec = 1024; + } + + _os_log_encode_arg(&prec, sizeof(prec), OS_LOG_BUFFER_VALUE_TYPE_COUNT, false, context); + } + break; + + case '-': // left-align + case '+': // force sign + case ' ': // prefix non-negative with space + case '#': // alternate + case '\'': // group by thousands + break; + + /* fixed types */ + case 'd': // integer + case 'i': // integer + case 'o': // octal + case 'u': // unsigned + case 'x': // hex + case 'X': // upper-hex + switch (type) { + case OST_CHAR: + value.type.ch = va_arg(args, int); + _os_log_encode_arg(&value.type.ch, sizeof(value.type.ch), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_SHORT: + value.type.s = va_arg(args, int); + _os_log_encode_arg(&value.type.s, sizeof(value.type.s), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_INT: + value.type.i = va_arg(args, int); + _os_log_encode_arg(&value.type.i, sizeof(value.type.i), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_LONG: + value.type.l = va_arg(args, long); + _os_log_encode_arg(&value.type.l, sizeof(value.type.l), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_LONGLONG: + value.type.ll = va_arg(args, long long); + _os_log_encode_arg(&value.type.ll, sizeof(value.type.ll), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_SIZE: + value.type.z = va_arg(args, size_t); + _os_log_encode_arg(&value.type.z, sizeof(value.type.z), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_INTMAX: + value.type.im = va_arg(args, intmax_t); + _os_log_encode_arg(&value.type.im, sizeof(value.type.im), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + case OST_PTRDIFF: + value.type.pd = va_arg(args, ptrdiff_t); + _os_log_encode_arg(&value.type.pd, sizeof(value.type.pd), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + break; + + default: + return false; + } + done = true; + break; + #ifndef KERNEL - case '{': - // we do not support this for shimmed code - if (context->shimmed) { - return false; - } - - for (const char *curr2 = percent + 1; (ch = (*curr2)) != NUL; curr2++) { - if (ch == '}') { - strlcpy(annotated, percent, MIN(curr2 - (percent + 1), sizeof(annotated))); - context->annotated = annotated; - percent = curr2; - break; - } - } - break; + case '{': + // we do not support this for shimmed code + if (context->shimmed) { + return false; + } + + for (const char *curr2 = percent + 1; (ch = (*curr2)) != NUL; curr2++) { + if (ch == '}') { + strlcpy(annotated, percent, MIN(curr2 - (percent + 1), sizeof(annotated))); + context->annotated = annotated; + percent = curr2; + break; + } + } + break; #endif /* !KERNEL */ - - case 'p': // pointer - value.type.p = va_arg(args, void *); - _os_log_encode_arg(&value.type.p, sizeof(value.type.p), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - done = true; - break; - + + case 'p': // pointer + value.type.p = va_arg(args, void *); + _os_log_encode_arg(&value.type.p, sizeof(value.type.p), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + done = true; + break; + #ifndef KERNEL - case 'P': // pointer data - if (context->shimmed) { // we do not support this for shimmed code - return false; - } - - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - value.type.p = va_arg(args, void *); - - // capture the string pointer to generate a symptom - if (context->log && context->log->generate_symptoms && context->arg_idx == 1 && value.type.pch && prec) { - context->symptom_ptr = value.type.p; - context->symptom_ptr_len = prec; - } - - _os_log_encode_arg(value.type.p, prec, OS_LOG_BUFFER_VALUE_TYPE_POINTER, false, context); - prec = 0; - done = true; - break; + case 'P': // pointer data + if (context->shimmed) { // we do not support this for shimmed code + return false; + } + + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + value.type.p = va_arg(args, void *); + + // capture the string pointer to generate a symptom + if (context->log && context->log->generate_symptoms && context->arg_idx == 1 && value.type.pch && prec) { + context->symptom_ptr = value.type.p; + context->symptom_ptr_len = prec; + } + + _os_log_encode_arg(value.type.p, prec, OS_LOG_BUFFER_VALUE_TYPE_POINTER, false, context); + prec = 0; + done = true; + break; #endif /* !KERNEL */ - + #ifndef KERNEL - case 'L': // long double - long_double = true; - break; - - case 'a': case 'A': case 'e': case 'E': // floating types - case 'f': case 'F': case 'g': case 'G': - if (long_double) { - value.type.ld = va_arg(args, long double); - _os_log_encode_arg(&value.type.ld, sizeof(value.type.ld), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - } else { - value.type.d = va_arg(args, double); - _os_log_encode_arg(&value.type.d, sizeof(value.type.d), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - } - done = true; - break; + case 'L': // long double + long_double = true; + break; + + case 'a': case 'A': case 'e': case 'E': // floating types + case 'f': case 'F': case 'g': case 'G': + if (long_double) { + value.type.ld = va_arg(args, long double); + _os_log_encode_arg(&value.type.ld, sizeof(value.type.ld), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + } else { + value.type.d = va_arg(args, double); + _os_log_encode_arg(&value.type.d, sizeof(value.type.d), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + } + done = true; + break; #endif /* !KERNEL */ - - case 'c': // char - value.type.ch = va_arg(args, int); - _os_log_encode_arg(&value.type.ch, sizeof(value.type.ch), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - done = true; - break; - + + case 'c': // char + value.type.ch = va_arg(args, int); + _os_log_encode_arg(&value.type.ch, sizeof(value.type.ch), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + done = true; + break; + #ifndef KERNEL - case 'C': // wide-char - value.type.wch = va_arg(args, wint_t); - _os_log_encode_arg(&value.type.wch, sizeof(value.type.wch), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - done = true; - break; + case 'C': // wide-char + value.type.wch = va_arg(args, wint_t); + _os_log_encode_arg(&value.type.wch, sizeof(value.type.wch), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + done = true; + break; #endif /* !KERNEL */ - - case 's': // string - value.type.pch = va_arg(args, char *); - if (!prec && value.type.pch != NULL) { - prec = (int) strlen(value.type.pch) + 1; - } - + + case 's': // string + value.type.pch = va_arg(args, char *); + if (!prec && value.type.pch != NULL) { + prec = (int) strlen(value.type.pch) + 1; + } + #ifndef KERNEL - // capture the string pointer to generate a symptom - if (context->log && context->log->generate_symptoms && context->arg_idx == 0 && value.type.pch) { - context->symptom_str = value.type.pch; - } + // capture the string pointer to generate a symptom + if (context->log && context->log->generate_symptoms && context->arg_idx == 0 && value.type.pch) { + context->symptom_str = value.type.pch; + } #endif - - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - _os_log_encode_arg(value.type.pch, prec, OS_LOG_BUFFER_VALUE_TYPE_STRING, false, context); - prec = 0; - done = true; - break; - + + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + _os_log_encode_arg(value.type.pch, prec, OS_LOG_BUFFER_VALUE_TYPE_STRING, false, context); + prec = 0; + done = true; + break; + #ifndef KERNEL - case 'S': // wide-string - value.type.pwch = va_arg(args, wchar_t *); - if (!prec && value.type.pwch != NULL) { - prec = (int) wcslen(value.type.pwch) + 1; - } - - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - _os_log_encode_arg(value.type.pwch, prec, OS_LOG_BUFFER_VALUE_TYPE_STRING, false, context); - prec = 0; - done = true; - break; + case 'S': // wide-string + value.type.pwch = va_arg(args, wchar_t *); + if (!prec && value.type.pwch != NULL) { + prec = (int) wcslen(value.type.pwch) + 1; + } + + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + _os_log_encode_arg(value.type.pwch, prec, OS_LOG_BUFFER_VALUE_TYPE_STRING, false, context); + prec = 0; + done = true; + break; #endif /* !KERNEL */ - + #ifndef KERNEL - case '@': // CFTypeRef aka NSObject * - context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; - _os_log_encode_arg(va_arg(args, void *), 0, OS_LOG_BUFFER_VALUE_TYPE_OBJECT, false, context); - done = true; - break; + case '@': // CFTypeRef aka NSObject * + context->buffer->flags |= OS_LOG_BUFFER_HAS_NON_SCALAR; + _os_log_encode_arg(va_arg(args, void *), 0, OS_LOG_BUFFER_VALUE_TYPE_OBJECT, false, context); + done = true; + break; #endif /* !KERNEL */ - - case 'm': - value.type.i = saved_errno; - _os_log_encode_arg(&value.type.i, sizeof(value.type.i), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); - done = true; - break; - - default: - if (isdigit(ch)) { // [0-9] - continue; - } - return false; - } - - if (done) { - percent = strchr(percent, '%'); // Find next format - break; - } - } - } else { - percent = strchr(percent+1, '%'); // Find next format after %% - } - } - - context->buffer->arg_cnt = context->arg_idx; - context->content_sz = context->content_off; - context->pubdata_sz = context->pubdata_off; - context->privdata_sz = context->privdata_off; - context->arg_idx = context->content_off = context->pubdata_off = context->privdata_off = 0; - - return true; + + case 'm': + value.type.i = saved_errno; + _os_log_encode_arg(&value.type.i, sizeof(value.type.i), OS_LOG_BUFFER_VALUE_TYPE_SCALAR, false, context); + done = true; + break; + + default: + if (isdigit(ch)) { // [0-9] + continue; + } + return false; + } + + if (done) { + percent = strchr(percent, '%'); // Find next format + break; + } + } + } else { + percent = strchr(percent + 1, '%'); // Find next format after %% + } + } + + context->buffer->arg_cnt = context->arg_idx; + context->content_sz = context->content_off; + context->pubdata_sz = context->pubdata_off; + context->privdata_sz = context->privdata_off; + context->arg_idx = context->content_off = context->pubdata_off = context->privdata_off = 0; + + return true; } #endif /* log_encode_h */