+ if (p->p_exit_reason != OS_REASON_NULL) {
+ if (KERN_SUCCESS == kcdata_get_memory_addr(crash_info_ptr, EXIT_REASON_SNAPSHOT, sizeof(struct exit_reason_snapshot), &uaddr)) {
+ struct exit_reason_snapshot ers = {
+ .ers_namespace = p->p_exit_reason->osr_namespace,
+ .ers_code = p->p_exit_reason->osr_code,
+ .ers_flags = p->p_exit_reason->osr_flags
+ };
+
+ kcdata_memcpy(crash_info_ptr, uaddr, &ers, sizeof(ers));
+ }
+
+ if (p->p_exit_reason->osr_kcd_buf != 0) {
+ uint32_t reason_buf_size = kcdata_memory_get_used_bytes(&p->p_exit_reason->osr_kcd_descriptor);
+ assert(reason_buf_size != 0);
+
+ if (KERN_SUCCESS == kcdata_get_memory_addr(crash_info_ptr, KCDATA_TYPE_NESTED_KCDATA, reason_buf_size, &uaddr)) {
+ kcdata_memcpy(crash_info_ptr, uaddr, p->p_exit_reason->osr_kcd_buf, reason_buf_size);
+ }
+ }
+ }
+
+ if (num_udata > 0) {
+ if (KERN_SUCCESS == kcdata_get_memory_addr_for_array(crash_info_ptr, TASK_CRASHINFO_UDATA_PTRS,
+ sizeof(uint64_t), num_udata, &uaddr)) {
+ kcdata_memcpy(crash_info_ptr, uaddr, udata_buffer, sizeof(uint64_t) * num_udata);
+ }
+ }
+}
+
+/*
+ * We only parse exit reason kcdata blobs for launchd when it dies
+ * and we're going to panic.
+ *
+ * Meant to be called immediately before panicking.
+ */
+char *
+launchd_exit_reason_get_string_desc(os_reason_t exit_reason)
+{
+ kcdata_iter_t iter;
+
+ if (exit_reason == OS_REASON_NULL || exit_reason->osr_kcd_buf == NULL ||
+ exit_reason->osr_bufsize == 0) {
+ return NULL;
+ }
+
+ iter = kcdata_iter(exit_reason->osr_kcd_buf, exit_reason->osr_bufsize);
+ if (!kcdata_iter_valid(iter)) {
+#if DEBUG || DEVELOPMENT
+ printf("launchd exit reason has invalid exit reason buffer\n");
+#endif
+ return NULL;
+ }
+
+ if (kcdata_iter_type(iter) != KCDATA_BUFFER_BEGIN_OS_REASON) {
+#if DEBUG || DEVELOPMENT
+ printf("launchd exit reason buffer type mismatch, expected %d got %d\n",
+ KCDATA_BUFFER_BEGIN_OS_REASON, kcdata_iter_type(iter));
+#endif
+ return NULL;
+ }
+
+ iter = kcdata_iter_find_type(iter, EXIT_REASON_USER_DESC);
+ if (!kcdata_iter_valid(iter)) {
+ return NULL;
+ }
+
+ return (char *)kcdata_iter_payload(iter);