xref: /xnu-12377.41.6/bsd/kern/kdebug_triage.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 /*
2  * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
3  *
4  * @Apple_LICENSE_HEADER_START@
5  *
6  * The contents of this file constitute Original Code as defined in and
7  * are subject to the Apple Public Source License Version 1.1 (the
8  * "License").  You may not use this file except in compliance with the
9  * License.  Please obtain a copy of the License at
10  * http://www.apple.com/publicsource and read it before using this file.
11  *
12  * This Original Code and all software distributed under the License are
13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17  * License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
21  */
22 
23 #include <sys/kdebug_common.h>
24 #include <sys/kdebug_triage.h>
25 #include <machine/atomic.h>
26 
27 #define TRIAGE_KDCOPYBUF_COUNT 128
28 #define TRIAGE_KDCOPYBUF_SIZE  (TRIAGE_KDCOPYBUF_COUNT * sizeof(kd_buf))
29 
30 struct kd_control kd_control_triage = {
31 	.kds_free_list = { .raw = KDS_PTR_NULL },
32 	.mode = KDEBUG_MODE_TRIAGE,
33 	.kdebug_events_per_storage_unit = TRIAGE_EVENTS_PER_STORAGE_UNIT,
34 	.kdebug_min_storage_units_per_cpu = TRIAGE_MIN_STORAGE_UNITS_PER_CPU,
35 	.kdc_flags = KDBG_DEBUGID_64,
36 	.kdc_emit = KDEMIT_DISABLE,
37 	.kdc_oldest_time = 0
38 };
39 
40 struct kd_buffer kd_buffer_triage = {
41 	.kdb_event_count = 0,
42 	.kdb_storage_count = 0,
43 	.kdb_storage_threshold = 0,
44 	.kdb_region_count = 0,
45 	.kdb_info = NULL,
46 	.kd_bufs = NULL,
47 	.kdcopybuf = NULL,
48 };
49 
50 static LCK_GRP_DECLARE(ktriage_grp, "ktriage");
51 static LCK_MTX_DECLARE(ktriage_mtx, &ktriage_grp);
52 
53 static void
ktriage_lock(void)54 ktriage_lock(void)
55 {
56 	lck_mtx_lock(&ktriage_mtx);
57 }
58 
59 static void
ktriage_unlock(void)60 ktriage_unlock(void)
61 {
62 	lck_mtx_unlock(&ktriage_mtx);
63 }
64 
65 __startup_func
66 void
create_buffers_triage(void)67 create_buffers_triage(void)
68 {
69 	if (kd_control_triage.kdc_flags & KDBG_BUFINIT) {
70 		panic("kdebug_triage: double-init");
71 	}
72 
73 	uint32_t cpu_count = kdbg_cpu_count();
74 	kd_control_triage.kdebug_cpus = cpu_count;
75 	kd_control_triage.alloc_cpus = cpu_count;
76 	uint32_t storage_count = cpu_count * kd_control_triage.kdebug_min_storage_units_per_cpu;
77 
78 	kd_buffer_triage.kdb_storage_count = storage_count;
79 	kd_buffer_triage.kdb_event_count = storage_count * kd_control_triage.kdebug_events_per_storage_unit;
80 
81 	int error = create_buffers(&kd_control_triage, &kd_buffer_triage, VM_KERN_MEMORY_TRIAGE);
82 	if (error != 0) {
83 		panic("kdebug_triage: failed to create buffers, error = %d", error);
84 	}
85 	// Immediately enable triage recording.
86 	kd_control_triage.enabled = 1;
87 }
88 
89 ktriage_strings_t ktriage_subsystems_strings[KDBG_TRIAGE_SUBSYS_MAX + 1];
90 
91 static void
ktriage_convert_to_string(uint64_t debugid,uintptr_t arg,char * buf,uint32_t bufsz)92 ktriage_convert_to_string(uint64_t debugid, uintptr_t arg, char *buf, uint32_t bufsz)
93 {
94 	if (buf == NULL) {
95 		return;
96 	}
97 
98 	uint8_t subsystem = KDBG_TRIAGE_EXTRACT_CLASS(debugid);
99 
100 	/* zero subsystem means there is nothing to log */
101 	if (subsystem == 0) {
102 		return;
103 	}
104 
105 	if (subsystem > KDBG_TRIAGE_SUBSYS_MAX) {
106 		snprintf(buf, bufsz, "KTriage Error: Subsystem code %u is invalid\n", subsystem);
107 		return;
108 	}
109 
110 	int subsystem_num_strings = ktriage_subsystems_strings[subsystem].num_strings;
111 	const char **subsystem_strings = ktriage_subsystems_strings[subsystem].strings;
112 	uint16_t strindx = KDBG_TRIAGE_EXTRACT_CODE(debugid);
113 
114 	/* fallback if ktriage doesn't know how to parse the given debugid */
115 	if (subsystem_num_strings < 1 || subsystem_strings == NULL || strindx >= subsystem_num_strings) {
116 		snprintf(buf, bufsz, "KTriage: Subsystem %d reported %u with argument 0x%lx\n", subsystem, strindx, arg);
117 		return;
118 	}
119 
120 	snprintf(buf, bufsz, "%s(arg = 0x%lx) %s", subsystem_strings[0], arg, subsystem_strings[strindx]);
121 
122 	return;
123 }
124 
125 static void
_write_triage_record_nopreempt(uintptr_t debugid,uintptr_t arg,uintptr_t thread_id)126 _write_triage_record_nopreempt(uintptr_t debugid, uintptr_t arg, uintptr_t thread_id)
127 {
128 	uint64_t now = 0;
129 	uint32_t bindx;
130 	kd_buf *kd;
131 	struct kd_storage *kdsp_actual;
132 	union kds_ptr kds_raw;
133 
134 	if (!kd_control_triage.enabled) {
135 		return;
136 	}
137 	int cpu = cpu_number();
138 	struct kd_bufinfo *info = &kd_buffer_triage.kdb_info[cpu];
139 	const uint32_t events_per_storage = kd_control_triage.kdebug_events_per_storage_unit;
140 
141 	while (true) {
142 		kds_raw = info->kd_list_tail;
143 
144 		if (kds_raw.raw != KDS_PTR_NULL) {
145 			kdsp_actual = POINTER_FROM_KDS_PTR(kd_buffer_triage.kd_bufs, kds_raw);
146 			bindx = kdsp_actual->kds_bufindx;
147 		} else {
148 			kdsp_actual = NULL;
149 			bindx = events_per_storage;
150 		}
151 
152 		if (kdsp_actual == NULL || bindx >= events_per_storage) {
153 			if (kdebug_storage_alloc(&kd_control_triage, &kd_buffer_triage, cpu) == false) {
154 				break;
155 			}
156 			continue;
157 		}
158 
159 		now = mach_continuous_time() & KDBG_TIMESTAMP_MASK;
160 		if (OSCompareAndSwap(bindx, bindx + 1, &kdsp_actual->kds_bufindx)) {
161 			kd = &kdsp_actual->kds_records[bindx];
162 
163 			kd->debugid = 0;
164 			kd->arg1 = arg;
165 			kd->arg2 = 0;
166 			kd->arg3 = 0;
167 			kd->arg4 = debugid;
168 			kd->arg5 = thread_id;
169 			kd->timestamp = now;
170 
171 			os_atomic_inc(&kdsp_actual->kds_bufcnt, release);
172 			break;
173 		}
174 	}
175 }
176 
177 void
ktriage_record(uint64_t thread_id,uint64_t debugid,uintptr_t arg)178 ktriage_record(
179 	uint64_t thread_id,
180 	uint64_t debugid,
181 	uintptr_t arg)
182 {
183 	if (thread_id == 0) {
184 		thread_id = thread_tid(current_thread());
185 	}
186 	disable_preemption();
187 	_write_triage_record_nopreempt(debugid, arg, thread_id);
188 	enable_preemption();
189 }
190 
191 static struct kd_storage *
_find_triage_min_storage(uint64_t thread_id)192 _find_triage_min_storage(uint64_t thread_id)
193 {
194 	uint64_t earliest_time = UINT64_MAX;
195 	struct kd_storage *min_store = NULL;
196 
197 	// Find the earliest record from all CPUs.
198 	for (unsigned int cpu = 0; cpu < kd_control_triage.kdebug_cpus; cpu++) {
199 		struct kd_bufinfo *info = &kd_buffer_triage.kdb_info[cpu];
200 		union kds_ptr store_ptr = info->kd_list_head;
201 		if (store_ptr.raw == KDS_PTR_NULL) {
202 			continue;
203 		}
204 		struct kd_storage *store = POINTER_FROM_KDS_PTR(kd_buffer_triage.kd_bufs, store_ptr);
205 		kd_buf *found_rec = NULL;
206 
207 		while (store) {
208 			unsigned int last_read = store->kds_readlast;
209 			unsigned int const limit = os_atomic_load(&store->kds_bufcnt, acquire);
210 			while (last_read < limit) {
211 				// Skip any records that didn't come from the target thread.
212 				kd_buf *rec = &store->kds_records[last_read];
213 				if (rec->arg5 == thread_id) {
214 					found_rec = rec;
215 					break;
216 				}
217 				last_read++;
218 			}
219 			if (found_rec) {
220 				store->kds_readlast = last_read;
221 				break;
222 			}
223 
224 			store_ptr = store->kds_next;
225 			if (store_ptr.raw == KDS_PTR_NULL) {
226 				break;
227 			}
228 			store = POINTER_FROM_KDS_PTR(kd_buffer_triage.kd_bufs, store_ptr);
229 		}
230 
231 		if (found_rec) {
232 			uint64_t t = found_rec->timestamp;
233 			if (t < earliest_time) {
234 				earliest_time = t;
235 				min_store = store;
236 			}
237 		}
238 	}
239 	return min_store;
240 }
241 
242 /// Copy a time-ordered series of records pertaining to the given thread to a
243 /// buffer.  Returns the number of records written into the buffer.
244 ///
245 /// Mutual exclusion must be provided by the caller.
246 ///
247 /// This is similar to `_read_trace_records`, except for a few triage-specific
248 /// additions and the removal of significant complexity for handling lost
249 /// events, coprocessors, and direct file writing.
250 static size_t
_read_triage_records(kd_buf * read_buffer,size_t max_count,uint64_t thread_id)251 _read_triage_records(kd_buf *read_buffer,
252     size_t max_count,
253     uint64_t thread_id)
254 {
255 	struct kd_bufinfo *bufinfos = kd_buffer_triage.kdb_info;
256 	struct kd_region *region = kd_buffer_triage.kd_bufs;
257 
258 	size_t avail_count = MIN(max_count, kd_buffer_triage.kdb_event_count);
259 	size_t read_count = 0;
260 
261 	if (avail_count == 0 ||
262 	    !(kd_control_triage.kdc_flags & KDBG_BUFINIT)) {
263 		return 0;
264 	}
265 
266 	// `thread_call` threads created due to corpse creation may already have the
267 	// eager preemption bit set, so don't over-do it.
268 	bool set_preempt = !(thread_is_eager_preempt(current_thread()));
269 	if (set_preempt) {
270 		thread_set_eager_preempt(current_thread());
271 	}
272 
273 	// Prevent any writers from stealing storage units -- just drop their logs
274 	// on the floor instead.
275 	int intrs_en = kdebug_storage_lock(&kd_control_triage);
276 	kd_control_triage.kdc_flags |= KDBG_NOWRAP;
277 	kdebug_storage_unlock(&kd_control_triage, intrs_en);
278 
279 	// Clear out any previous accumulated state from earlier reads, as triage
280 	// wants to reconsider all available data.
281 	for (unsigned int cpu = 0; cpu < kd_control_triage.kdebug_cpus; cpu++) {
282 		struct kd_bufinfo *info = &bufinfos[cpu];
283 		info->kd_prev_timebase = 0;
284 		union kds_ptr kdsp = info->kd_list_head;
285 		while (kdsp.raw != KDS_PTR_NULL) {
286 			struct kd_storage *store = POINTER_FROM_KDS_PTR(region, kdsp);
287 			store->kds_readlast = 0;
288 			kdsp = store->kds_next;
289 		}
290 	}
291 
292 	while (avail_count) {
293 		struct kd_storage *min_store = _find_triage_min_storage(thread_id);
294 		if (min_store == NULL) {
295 			break;
296 		}
297 		*read_buffer++ = min_store->kds_records[min_store->kds_readlast++];
298 		avail_count--;
299 		read_count++;
300 	}
301 
302 	intrs_en = kdebug_storage_lock(&kd_control_triage);
303 	kd_control_triage.kdc_flags &= ~KDBG_NOWRAP;
304 	kdebug_storage_unlock(&kd_control_triage, intrs_en);
305 	if (set_preempt) {
306 		thread_clear_eager_preempt(current_thread());
307 	}
308 
309 	return read_count;
310 }
311 
312 void
ktriage_extract(uint64_t thread_id,void * buf,uint32_t bufsz)313 ktriage_extract(
314 	uint64_t thread_id,
315 	void *buf,
316 	uint32_t bufsz)
317 {
318 	size_t record_cnt = 0, record_bufsz;
319 	void *record_buf;
320 	void *local_buf;
321 
322 	if (thread_id == 0 || buf == NULL || bufsz < KDBG_TRIAGE_MAX_STRLEN) {
323 		return;
324 	}
325 
326 	local_buf = buf;
327 	bzero(local_buf, bufsz);
328 
329 	record_bufsz = kd_buffer_triage.kdb_event_count * sizeof(kd_buf);
330 	record_buf = kalloc_data(record_bufsz, Z_WAITOK);
331 	if (record_buf == NULL) {
332 		printf("kdebug_triage: failed to allocate %lu bytes for record\n",
333 		    record_bufsz);
334 		return;
335 	} else {
336 		ktriage_lock();
337 		record_cnt = _read_triage_records(record_buf,
338 		    kd_buffer_triage.kdb_event_count, thread_id);
339 		ktriage_unlock();
340 	}
341 
342 	kd_buf *kd = (kd_buf *)record_buf;
343 	for (size_t i = 0; i < record_cnt; i++) {
344 		assert3u(kd->arg5, ==, thread_id);
345 		ktriage_convert_to_string(kd->arg4, kd->arg1, local_buf, KDBG_TRIAGE_MAX_STRLEN);
346 		local_buf = (void *)((uintptr_t)local_buf + KDBG_TRIAGE_MAX_STRLEN);
347 		bufsz -= KDBG_TRIAGE_MAX_STRLEN;
348 		if (bufsz < KDBG_TRIAGE_MAX_STRLEN) {
349 			break;
350 		}
351 		kd++;
352 	}
353 
354 	kfree_data(record_buf, record_bufsz);
355 }
356 
357 int
ktriage_register_subsystem_strings(uint8_t subsystem,ktriage_strings_t * subsystem_strings)358 ktriage_register_subsystem_strings(uint8_t subsystem, ktriage_strings_t *subsystem_strings)
359 {
360 	if (subsystem == 0 || subsystem > KDBG_TRIAGE_SUBSYS_MAX || subsystem_strings == NULL) {
361 		return EINVAL;
362 	}
363 
364 	ktriage_lock();
365 
366 	ktriage_subsystems_strings[subsystem].num_strings = subsystem_strings->num_strings;
367 	ktriage_subsystems_strings[subsystem].strings = subsystem_strings->strings;
368 	printf("ktriage_register_subsystem_strings: set subsystem %u strings\n", subsystem);
369 
370 	ktriage_unlock();
371 
372 	return 0;
373 }
374 
375 int
ktriage_unregister_subsystem_strings(uint8_t subsystem)376 ktriage_unregister_subsystem_strings(uint8_t subsystem)
377 {
378 	if (subsystem == 0 || subsystem > KDBG_TRIAGE_SUBSYS_MAX) {
379 		return EINVAL;
380 	}
381 
382 	ktriage_lock();
383 
384 	if (ktriage_subsystems_strings[subsystem].num_strings == -1) {
385 		// already unregistered - nothing to do
386 		ktriage_unlock();
387 		return 0;
388 	}
389 
390 	ktriage_subsystems_strings[subsystem].num_strings = -1;
391 	ktriage_subsystems_strings[subsystem].strings = NULL;
392 
393 	ktriage_unlock();
394 
395 	return 0;
396 }
397 
398 /* KDBG_TRIAGE_CODE_* section */
399 /* VM begin */
400 
401 const char *vm_triage_strings[] =
402 {
403 	[KDBG_TRIAGE_VM_PREFIX] = "VM - ",
404 	[KDBG_TRIAGE_VM_NO_DATA] = "Didn't get back data for this file\n",
405 	[KDBG_TRIAGE_VM_TEXT_CORRUPTION] = "A memory corruption was found in executable text\n",
406 	[KDBG_TRIAGE_VM_ADDRESS_NOT_FOUND] = "Found no valid range containing this address\n",
407 	[KDBG_TRIAGE_VM_PROTECTION_FAILURE] = "Fault hit protection failure\n",
408 	[KDBG_TRIAGE_VM_FAULT_MEMORY_SHORTAGE] = "VM Fault hit memory shortage\n",
409 	[KDBG_TRIAGE_VM_FAULT_COPY_MEMORY_SHORTAGE] = "vm_fault_copy hit memory shortage\n",
410 	[KDBG_TRIAGE_VM_FAULT_OBJCOPYSLOWLY_MEMORY_SHORTAGE] = "vm_object_copy_slowly fault hit memory shortage\n",
411 	[KDBG_TRIAGE_VM_FAULT_OBJIOPLREQ_MEMORY_SHORTAGE] = "vm_object_iopl_request fault hit memory shortage\n",
412 	[KDBG_TRIAGE_VM_FAULT_INTERRUPTED] = "Fault was interrupted\n",
413 	[KDBG_TRIAGE_VM_SUCCESS_NO_PAGE] = "Returned success with no page\n",
414 	[KDBG_TRIAGE_VM_GUARDPAGE_FAULT] = "Guard page fault\n",
415 	[KDBG_TRIAGE_VM_NONZERO_PREEMPTION_LEVEL] = "Fault entered with non-zero preemption level\n",
416 	[KDBG_TRIAGE_VM_BUSYPAGE_WAIT_INTERRUPTED] = "Waiting on busy page was interrupted\n",
417 	[KDBG_TRIAGE_VM_PURGEABLE_FAULT_ERROR] = "Purgeable object hit an error in fault\n",
418 	[KDBG_TRIAGE_VM_OBJECT_SHADOW_SEVERED] = "Object has a shadow severed\n",
419 	[KDBG_TRIAGE_VM_OBJECT_NOT_ALIVE] = "Object is not alive\n",
420 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER] = "Object has no pager\n",
421 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_RECLAIM] = "Object has no pager because the backing vnode was reclaimed\n",
422 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_UNMOUNT] = "Object has no pager because the backing vnode was unmounted\n",
423 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_FORCED_UNMOUNT] = "Object has no pager because the backing vnode was force unmounted\n",
424 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_UNGRAFT] = "Object has no pager because the backing vnode was ungrafted\n",
425 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_DEALLOC_PAGER] = "Object has no pager because the pager was deallocated\n",
426 	[KDBG_TRIAGE_VM_PAGE_HAS_ERROR] = "Page has error bit set\n",
427 	[KDBG_TRIAGE_VM_PAGE_HAS_RESTART] = "Page has restart bit set\n",
428 	[KDBG_TRIAGE_VM_FAILED_IMMUTABLE_PAGE_WRITE] = "Failed a writable mapping of an immutable page\n",
429 	[KDBG_TRIAGE_VM_FAILED_NX_PAGE_EXEC_MAPPING] = "Failed an executable mapping of a nx page\n",
430 	[KDBG_TRIAGE_VM_PMAP_ENTER_RESOURCE_SHORTAGE] = "pmap_enter retried due to resource shortage\n",
431 	[KDBG_TRIAGE_VM_COMPRESSOR_GET_OUT_OF_RANGE] = "Compressor offset requested out of range\n",
432 	[KDBG_TRIAGE_VM_COMPRESSOR_GET_NO_PAGE] = "Compressor doesn't have this page\n",
433 	[KDBG_TRIAGE_VM_COMPRESSOR_DECOMPRESS_FAILED] = "Decompressor hit a failure\n",
434 	[KDBG_TRIAGE_VM_COMPRESSOR_DECOMPRESS_POPCNT_MISMATCH] = "Decompressor popcnt mismatch\n",
435 	[KDBG_TRIAGE_VM_SUBMAP_NO_COW_ON_EXECUTABLE] = "Submap disallowed cow on executable range\n",
436 	[KDBG_TRIAGE_VM_SUBMAP_COPY_SLOWLY_FAILED] = "Submap object copy_slowly failed\n",
437 	[KDBG_TRIAGE_VM_SUBMAP_COPY_STRAT_FAILED] = "Submap object copy_strategically failed\n",
438 	[KDBG_TRIAGE_VM_VNODEPAGER_CLREAD_NO_UPL] = "vnode_pager_cluster_read couldn't create a UPL\n",
439 	[KDBG_TRIAGE_VM_VNODEPAGEIN_NO_UBCINFO] = "vnode_pagein got a vnode with no ubcinfo\n",
440 	[KDBG_TRIAGE_VM_VNODEPAGEIN_FSPAGEIN_FAIL] = "Filesystem pagein returned an error in vnode_pagein\n",
441 	[KDBG_TRIAGE_VM_VNODEPAGEIN_NO_UPL] = "vnode_pagein couldn't create a UPL\n",
442 	[KDBG_TRIAGE_VM_ECC_DIRTY] = "Accessed a page that has uncorrected ECC error\n",
443 	[KDBG_TRIAGE_VM_ECC_CLEAN] = "Clean page had an uncorrected ECC error\n",
444 	[KDBG_TRIAGE_VM_COPYOUTMAP_SAMEMAP_ERROR] = "vm_copyout_map failed with same src-dest map\n",
445 	[KDBG_TRIAGE_VM_COPYOUTMAP_DIFFERENTMAP_ERROR] = "vm_copyout_map failed with different src-dest map\n",
446 	[KDBG_TRIAGE_VM_COPYOVERWRITE_FULL_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying full copy\n",
447 	[KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying partial copy\n",
448 	[KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_HEAD_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying misaligned head copy\n",
449 	[KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_TAIL_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying misaligned tail copy\n",
450 	[KDBG_TRIAGE_VM_COPYOUT_INTERNAL_SIZE_ERROR] = "vm_map_copyout_internal failed due to bad size\n",
451 	[KDBG_TRIAGE_VM_COPYOUT_KERNEL_BUFFER_ERROR] = "vm_map_copyout_kernel_buffer failed\n",
452 	[KDBG_TRIAGE_VM_COPYOUT_INTERNAL_ADJUSTING_ERROR] = "vm_map_copyout_internal failed when trying to adjust src-dest params\n",
453 	[KDBG_TRIAGE_VM_COPYOUT_INTERNAL_SPACE_ERROR] = "vm_map_copyout_internal failed because we couldn't locate space\n",
454 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_BADFLAGS_ERROR] = "mach_vm_allocate_kernel failed due to bad flags\n",
455 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_BADMAP_ERROR] = "mach_vm_allocate_kernel failed due to bad map\n",
456 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_BADSIZE_ERROR] = "mach_vm_allocate_kernel failed due to bad size\n",
457 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_VMMAPENTER_ERROR] = "mach_vm_allocate_kernel failed within call to vm_map_enter\n",
458 	[KDBG_TRIAGE_VM_IOPL_ON_EXEC_PAGE] = "Attempted I/O wiring of page with executable mapping\n",
459 	[KDBG_TRIAGE_VM_EXEC_ON_IOPL_PAGE] = "Attempted executable mapping of page already wired for I/O\n",
460 	[KDBG_TRIAGE_VM_UPL_WRITE_ON_EXEC_REGION] = "Attempted writable UPL against executable VM region\n",
461 };
462 /* VM end */
463 
464 /* Cluster begin */
465 
466 const char *cluster_triage_strings[] =
467 {
468 	[KDBG_TRIAGE_CL_PREFIX] = "CL - ",
469 	[KDBG_TRIAGE_CL_PGIN_PAST_EOF] = "cluster_pagein past EOF\n",
470 };
471 /* Cluster end */
472 
473 /* Shared Region begin */
474 
475 const char *shared_region_triage_strings[] =
476 {
477 	[KDBG_TRIAGE_SHARED_REGION_PREFIX] = "SR - ",
478 	[KDBG_TRIAGE_SHARED_REGION_NO_UPL] = "shared_region_pager_data_request couldn't create a upl\n",
479 	[KDBG_TRIAGE_SHARED_REGION_SLIDE_ERROR] = "shared_region_pager_data_request hit a page sliding error\n",
480 	[KDBG_TRIAGE_SHARED_REGION_PAGER_MEMORY_SHORTAGE] = "shared_region_pager_data_request hit memory shortage\n",
481 };
482 /* Shared Region end */
483 
484 /* Dyld Pager begin */
485 
486 const char *dyld_pager_triage_strings[] =
487 {
488 	[KDBG_TRIAGE_DYLD_PAGER_PREFIX] = "DP - ",
489 	[KDBG_TRIAGE_DYLD_PAGER_NO_UPL] = "dyld_pager_data_request couldn't create a upl\n",
490 	[KDBG_TRIAGE_DYLD_PAGER_MEMORY_SHORTAGE] = "dyld_pager_data_request hit memory shortage\n",
491 	[KDBG_TRIAGE_DYLD_PAGER_SLIDE_ERROR] = "dyld_pager_data_request hit a page sliding error\n",
492 	[KDBG_TRIAGE_DYLD_PAGER_CHAIN_OUT_OF_RANGE] = "dyld_pager_data_request chain out of range\n",
493 	[KDBG_TRIAGE_DYLD_PAGER_SEG_INFO_OUT_OF_RANGE] = "dyld_pager_data_request seg_info out of range\n",
494 	[KDBG_TRIAGE_DYLD_PAGER_SEG_SIZE_OUT_OF_RANGE] = "dyld_pager_data_request seg->size out of range\n",
495 	[KDBG_TRIAGE_DYLD_PAGER_SEG_PAGE_CNT_OUT_OF_RANGE] = "dyld_pager_data_request seg->page_count out of range\n",
496 	[KDBG_TRIAGE_DYLD_PAGER_NO_SEG_FOR_VA] = "dyld_pager_data_request no segment for VA\n",
497 	[KDBG_TRIAGE_DYLD_PAGER_RANGE_NOT_FOUND] = "dyld_pager_data_request no range for offset\n",
498 	[KDBG_TRIAGE_DYLD_PAGER_DELTA_TOO_LARGE] = "dyld_pager_data_request delta * 4 > PAGE_SIZE\n",
499 	[KDBG_TRIAGE_DYLD_PAGER_PAGE_START_OUT_OF_RANGE] = "dyld_pager_data_request segInfo page_start out of range\n",
500 	[KDBG_TRIAGE_DYLD_PAGER_BAD_POINTER_FMT] = "dyld_pager_data_request unkown pointer format\n",
501 	[KDBG_TRIAGE_DYLD_PAGER_INVALID_AUTH_KEY] = "dyld_pager_data_request unkown auth key\n",
502 	[KDBG_TRIAGE_DYLD_PAGER_BIND_ORDINAL] = "dyld_pager_data_request invalid bind ordinal\n",
503 };
504 /* Dyld Pager end */
505 
506 /* Apple Protect Pager begin */
507 
508 const char *apple_protect_pager_triage_strings[] =
509 {
510 	[KDBG_TRIAGE_APPLE_PROTECT_PAGER_PREFIX] = "APP - ",
511 	[KDBG_TRIAGE_APPLE_PROTECT_PAGER_MEMORY_SHORTAGE] = "apple_protect_pager_data_request hit memory shortage\n",
512 };
513 /* Apple Protect Pager end */
514 
515 /* Corpse section begin */
516 
517 const char *corpse_triage_strings[] =
518 {
519 	[KDBG_TRIAGE_CORPSE_PREFIX] = "Corpse - ",
520 	[KDBG_TRIAGE_CORPSE_PROC_TOO_BIG] = "Process too big for corpse. Corpse disallowed.\n",
521 	[KDBG_TRIAGE_CORPSE_FAIL_LIBGMALLOC] = "Process linked against libgmalloc. Corpse disallowed.\n",
522 	[KDBG_TRIAGE_CORPSE_BLOCKED_JETSAM] = "Jetsams happening in higher bands. Corpse disallowed.\n",
523 	[KDBG_TRIAGE_CORPSE_LIMIT] = "Too many corpses in flight. Corpse disallowed.\n",
524 	[KDBG_TRIAGE_CORPSES_DISABLED] = "Corpse disabled on system.\n",
525 	[KDBG_TRIAGE_CORPSE_DISABLED_FOR_PROC] = "Corpse disabled for this process.\n",
526 };
527 /* Corpse section end */
528 
529 /* subsystems starts at index 1 */
530 ktriage_strings_t ktriage_subsystems_strings[KDBG_TRIAGE_SUBSYS_MAX + 1] = {
531 	/* Static subsystems */
532 	[KDBG_TRIAGE_SUBSYS_VM]            = {VM_MAX_TRIAGE_STRINGS, vm_triage_strings},
533 	[KDBG_TRIAGE_SUBSYS_CLUSTER]       = {CLUSTER_MAX_TRIAGE_STRINGS, cluster_triage_strings},
534 	[KDBG_TRIAGE_SUBSYS_SHARED_REGION] = {SHARED_REGION_MAX_TRIAGE_STRINGS, shared_region_triage_strings},
535 	[KDBG_TRIAGE_SUBSYS_DYLD_PAGER]    = {DYLD_PAGER_MAX_TRIAGE_STRINGS, dyld_pager_triage_strings},
536 	[KDBG_TRIAGE_SUBSYS_APPLE_PROTECT_PAGER] = {APPLE_PROTECT_PAGER_MAX_TRIAGE_STRINGS, apple_protect_pager_triage_strings},
537 	[KDBG_TRIAGE_SUBSYS_CORPSE]        = {CORPSE_MAX_TRIAGE_STRINGS, corpse_triage_strings},
538 
539 	/* Dynamic subsystems */
540 	[KDBG_TRIAGE_SUBSYS_APFS]          = {-1, NULL},
541 	[KDBG_TRIAGE_SUBSYS_DECMPFS]       = {-1, NULL},
542 	[KDBG_TRIAGE_SUBSYS_VM_SANITIZE]   = {-1, NULL},
543 };
544 
545 /* KDBG_TRIAGE_CODE_* section */
546