xref: /xnu-11215.61.5/bsd/kern/kdebug_triage.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
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 
26 #define TRIAGE_KDCOPYBUF_COUNT 128
27 #define TRIAGE_KDCOPYBUF_SIZE  (TRIAGE_KDCOPYBUF_COUNT * sizeof(kd_buf))
28 
29 struct kd_control kd_control_triage = {
30 	.kds_free_list = { .raw = KDS_PTR_NULL },
31 	.mode = KDEBUG_MODE_TRIAGE,
32 	.kdebug_events_per_storage_unit = TRIAGE_EVENTS_PER_STORAGE_UNIT,
33 	.kdebug_min_storage_units_per_cpu = TRIAGE_MIN_STORAGE_UNITS_PER_CPU,
34 	.kdebug_kdcopybuf_count = TRIAGE_KDCOPYBUF_COUNT,
35 	.kdebug_kdcopybuf_size = TRIAGE_KDCOPYBUF_SIZE,
36 	.kdc_flags = KDBG_DEBUGID_64,
37 	.kdc_emit = KDEMIT_DISABLE,
38 	.kdc_oldest_time = 0
39 };
40 
41 struct kd_buffer kd_buffer_triage = {
42 	.kdb_event_count = 0,
43 	.kdb_storage_count = 0,
44 	.kdb_storage_threshold = 0,
45 	.kdb_region_count = 0,
46 	.kdb_info = NULL,
47 	.kd_bufs = NULL,
48 	.kdcopybuf = NULL
49 };
50 
51 
52 static LCK_GRP_DECLARE(ktriage_grp, "ktriage");
53 static LCK_MTX_DECLARE(ktriage_mtx, &ktriage_grp);
54 
55 static void
ktriage_lock(void)56 ktriage_lock(void)
57 {
58 	lck_mtx_lock(&ktriage_mtx);
59 }
60 
61 static void
ktriage_unlock(void)62 ktriage_unlock(void)
63 {
64 	lck_mtx_unlock(&ktriage_mtx);
65 }
66 
67 int
create_buffers_triage(void)68 create_buffers_triage(void)
69 {
70 	int error = 0;
71 	int events_per_storage_unit, min_storage_units_per_cpu;
72 
73 	if (kd_control_triage.kdc_flags & KDBG_BUFINIT) {
74 		panic("create_buffers_triage shouldn't be called once we have inited the triage system.");
75 	}
76 
77 	events_per_storage_unit = kd_control_triage.kdebug_events_per_storage_unit;
78 	min_storage_units_per_cpu = kd_control_triage.kdebug_min_storage_units_per_cpu;
79 
80 	kd_control_triage.kdebug_cpus = kdbg_cpu_count();
81 	kd_control_triage.alloc_cpus = kd_control_triage.kdebug_cpus;
82 	kd_control_triage.kdc_coprocs = NULL;
83 
84 	if (kd_buffer_triage.kdb_event_count < (kd_control_triage.kdebug_cpus * events_per_storage_unit * min_storage_units_per_cpu)) {
85 		kd_buffer_triage.kdb_storage_count = kd_control_triage.kdebug_cpus * min_storage_units_per_cpu;
86 	} else {
87 		kd_buffer_triage.kdb_storage_count = kd_buffer_triage.kdb_event_count / events_per_storage_unit;
88 	}
89 
90 	kd_buffer_triage.kdb_event_count = kd_buffer_triage.kdb_storage_count * events_per_storage_unit;
91 
92 	kd_buffer_triage.kd_bufs = NULL;
93 
94 	error = create_buffers(&kd_control_triage, &kd_buffer_triage, VM_KERN_MEMORY_TRIAGE);
95 
96 	if (!error) {
97 		kd_control_triage.kdc_oldest_time = mach_continuous_time();
98 		kd_control_triage.enabled = 1;
99 		kd_buffer_triage.kdb_storage_threshold = kd_buffer_triage.kdb_storage_count / 2;
100 	}
101 
102 	return error;
103 }
104 
105 __attribute__((noreturn))
106 void
delete_buffers_triage(void)107 delete_buffers_triage(void)
108 {
109 	/*
110 	 * If create_buffers() for triage mode fails, it will call the generic delete_buffers() to
111 	 * free the resources. This specific call should never be invoked because we expect the
112 	 * triage system to always be ON.
113 	 */
114 	panic("delete_buffers_triage shouldn't be invoked");
115 }
116 
117 ktriage_strings_t ktriage_subsystems_strings[KDBG_TRIAGE_SUBSYS_MAX + 1];
118 
119 static void
ktriage_convert_to_string(uint64_t debugid,uintptr_t arg,char * buf,uint32_t bufsz)120 ktriage_convert_to_string(uint64_t debugid, uintptr_t arg, char *buf, uint32_t bufsz)
121 {
122 	if (buf == NULL) {
123 		return;
124 	}
125 
126 	uint8_t subsystem = KDBG_TRIAGE_EXTRACT_CLASS(debugid);
127 
128 	/* zero subsystem means there is nothing to log */
129 	if (subsystem == 0) {
130 		return;
131 	}
132 
133 	if (subsystem > KDBG_TRIAGE_SUBSYS_MAX) {
134 		snprintf(buf, bufsz, "KTriage Error: Subsystem code %u is invalid\n", subsystem);
135 		return;
136 	}
137 
138 	int subsystem_num_strings = ktriage_subsystems_strings[subsystem].num_strings;
139 	const char **subsystem_strings = ktriage_subsystems_strings[subsystem].strings;
140 	uint16_t strindx = KDBG_TRIAGE_EXTRACT_CODE(debugid);
141 
142 	/* fallback if ktriage doesn't know how to parse the given debugid */
143 	if (subsystem_num_strings < 1 || subsystem_strings == NULL || strindx >= subsystem_num_strings) {
144 		snprintf(buf, bufsz, "KTriage: Subsystem %d reported %u with argument 0x%lx\n", subsystem, strindx, arg);
145 		return;
146 	}
147 
148 	snprintf(buf, bufsz, "%s(arg = 0x%lx) %s", subsystem_strings[0], arg, subsystem_strings[strindx]);
149 
150 	return;
151 }
152 
153 void
ktriage_record(uint64_t thread_id,uint64_t debugid,uintptr_t arg)154 ktriage_record(
155 	uint64_t thread_id,
156 	uint64_t debugid,
157 	uintptr_t arg)
158 {
159 	struct kd_record kd_rec;
160 
161 	if (thread_id == 0) {
162 		thread_id = thread_tid(current_thread());
163 	}
164 
165 	kd_rec.cpu = -1;
166 	kd_rec.timestamp = -1;
167 
168 	/*
169 	 * use 64-bit debugid per our flag KDBG_DEBUGID_64
170 	 * that is set in kd_control_triage (on LP64 only).
171 	 */
172 	assert(kd_control_triage.kdc_flags & KDBG_DEBUGID_64);
173 
174 	kd_rec.debugid = 0;
175 	kd_rec.arg4 = (uintptr_t)debugid;
176 
177 	kd_rec.arg1 = arg;
178 	kd_rec.arg2 = 0;
179 	kd_rec.arg3 = 0;
180 	kd_rec.arg5 = (uintptr_t)thread_id;
181 
182 	kernel_debug_write(&kd_control_triage,
183 	    &kd_buffer_triage,
184 	    kd_rec);
185 }
186 
187 void
ktriage_extract(uint64_t thread_id,void * buf,uint32_t bufsz)188 ktriage_extract(
189 	uint64_t thread_id,
190 	void *buf,
191 	uint32_t bufsz)
192 {
193 	size_t i, record_bytes, record_cnt, record_bufsz;
194 	void *record_buf;
195 	void *local_buf;
196 	int ret;
197 
198 
199 	if (thread_id == 0 || buf == NULL || bufsz < KDBG_TRIAGE_MAX_STRLEN) {
200 		return;
201 	}
202 
203 	local_buf = buf;
204 	bzero(local_buf, bufsz);
205 
206 	record_bytes = record_bufsz = kd_buffer_triage.kdb_event_count * sizeof(kd_buf);
207 	record_buf = kalloc_data(record_bufsz, Z_WAITOK);
208 
209 	if (record_buf == NULL) {
210 		ret = ENOMEM;
211 	} else {
212 		ktriage_lock();
213 		ret = kernel_debug_read(&kd_control_triage,
214 		    &kd_buffer_triage,
215 		    (user_addr_t) record_buf, &record_bytes, NULL, NULL, 0);
216 		ktriage_unlock();
217 	}
218 
219 	if (ret) {
220 		printf("ktriage_extract: kernel_debug_read failed with %d\n", ret);
221 		kfree_data(record_buf, record_bufsz);
222 		return;
223 	}
224 
225 	kd_buf *kd = (kd_buf*) record_buf;
226 	i = 0;
227 	record_cnt = record_bytes; /* kernel_debug_read() takes number of bytes that it
228 	                            * converts to kd_bufs. It processes a max of those and
229 	                            * returns number of kd_buf read/processed. We use a
230 	                            * different variable here to make our units clear.
231 	                            */
232 
233 	while (i < record_cnt) {
234 		if (kd->arg5 == (uintptr_t)thread_id) {
235 			ktriage_convert_to_string(kd->arg4, kd->arg1, local_buf, KDBG_TRIAGE_MAX_STRLEN);
236 			local_buf = (void *)((uintptr_t)local_buf + KDBG_TRIAGE_MAX_STRLEN);
237 			bufsz -= KDBG_TRIAGE_MAX_STRLEN;
238 			if (bufsz < KDBG_TRIAGE_MAX_STRLEN) {
239 				break;
240 			}
241 		}
242 		i++;
243 		kd++;
244 	}
245 
246 	kfree_data(record_buf, record_bufsz);
247 }
248 
249 int
ktriage_register_subsystem_strings(uint8_t subsystem,ktriage_strings_t * subsystem_strings)250 ktriage_register_subsystem_strings(uint8_t subsystem, ktriage_strings_t *subsystem_strings)
251 {
252 	if (subsystem == 0 || subsystem > KDBG_TRIAGE_SUBSYS_MAX || subsystem_strings == NULL) {
253 		return EINVAL;
254 	}
255 
256 	ktriage_lock();
257 
258 	ktriage_subsystems_strings[subsystem].num_strings = subsystem_strings->num_strings;
259 	ktriage_subsystems_strings[subsystem].strings = subsystem_strings->strings;
260 	printf("ktriage_register_subsystem_strings: set subsystem %u strings\n", subsystem);
261 
262 	ktriage_unlock();
263 
264 	return 0;
265 }
266 
267 int
ktriage_unregister_subsystem_strings(uint8_t subsystem)268 ktriage_unregister_subsystem_strings(uint8_t subsystem)
269 {
270 	if (subsystem == 0 || subsystem > KDBG_TRIAGE_SUBSYS_MAX) {
271 		return EINVAL;
272 	}
273 
274 	ktriage_lock();
275 
276 	if (ktriage_subsystems_strings[subsystem].num_strings == -1) {
277 		// already unregistered - nothing to do
278 		ktriage_unlock();
279 		return 0;
280 	}
281 
282 	ktriage_subsystems_strings[subsystem].num_strings = -1;
283 	ktriage_subsystems_strings[subsystem].strings = NULL;
284 
285 	ktriage_unlock();
286 
287 	return 0;
288 }
289 
290 /* KDBG_TRIAGE_CODE_* section */
291 /* VM begin */
292 
293 const char *vm_triage_strings[] =
294 {
295 	[KDBG_TRIAGE_VM_PREFIX] = "VM - ",
296 	[KDBG_TRIAGE_VM_NO_DATA] = "Didn't get back data for this file\n",
297 	[KDBG_TRIAGE_VM_TEXT_CORRUPTION] = "A memory corruption was found in executable text\n",
298 	[KDBG_TRIAGE_VM_ADDRESS_NOT_FOUND] = "Found no valid range containing this address\n",
299 	[KDBG_TRIAGE_VM_PROTECTION_FAILURE] = "Fault hit protection failure\n",
300 	[KDBG_TRIAGE_VM_FAULT_MEMORY_SHORTAGE] = "VM Fault hit memory shortage\n",
301 	[KDBG_TRIAGE_VM_FAULT_COPY_MEMORY_SHORTAGE] = "vm_fault_copy hit memory shortage\n",
302 	[KDBG_TRIAGE_VM_FAULT_OBJCOPYSLOWLY_MEMORY_SHORTAGE] = "vm_object_copy_slowly fault hit memory shortage\n",
303 	[KDBG_TRIAGE_VM_FAULT_OBJIOPLREQ_MEMORY_SHORTAGE] = "vm_object_iopl_request fault hit memory shortage\n",
304 	[KDBG_TRIAGE_VM_FAULT_INTERRUPTED] = "Fault was interrupted\n",
305 	[KDBG_TRIAGE_VM_SUCCESS_NO_PAGE] = "Returned success with no page\n",
306 	[KDBG_TRIAGE_VM_GUARDPAGE_FAULT] = "Guard page fault\n",
307 	[KDBG_TRIAGE_VM_NONZERO_PREEMPTION_LEVEL] = "Fault entered with non-zero preemption level\n",
308 	[KDBG_TRIAGE_VM_BUSYPAGE_WAIT_INTERRUPTED] = "Waiting on busy page was interrupted\n",
309 	[KDBG_TRIAGE_VM_PURGEABLE_FAULT_ERROR] = "Purgeable object hit an error in fault\n",
310 	[KDBG_TRIAGE_VM_OBJECT_SHADOW_SEVERED] = "Object has a shadow severed\n",
311 	[KDBG_TRIAGE_VM_OBJECT_NOT_ALIVE] = "Object is not alive\n",
312 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER] = "Object has no pager\n",
313 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_RECLAIM] = "Object has no pager because the backing vnode was reclaimed\n",
314 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_UNMOUNT] = "Object has no pager because the backing vnode was unmounted\n",
315 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_FORCED_UNMOUNT] = "Object has no pager because the backing vnode was force unmounted\n",
316 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_UNGRAFT] = "Object has no pager because the backing vnode was ungrafted\n",
317 	[KDBG_TRIAGE_VM_OBJECT_NO_PAGER_DEALLOC_PAGER] = "Object has no pager because the pager was deallocated\n",
318 	[KDBG_TRIAGE_VM_PAGE_HAS_ERROR] = "Page has error bit set\n",
319 	[KDBG_TRIAGE_VM_PAGE_HAS_RESTART] = "Page has restart bit set\n",
320 	[KDBG_TRIAGE_VM_FAILED_IMMUTABLE_PAGE_WRITE] = "Failed a writable mapping of an immutable page\n",
321 	[KDBG_TRIAGE_VM_FAILED_NX_PAGE_EXEC_MAPPING] = "Failed an executable mapping of a nx page\n",
322 	[KDBG_TRIAGE_VM_PMAP_ENTER_RESOURCE_SHORTAGE] = "pmap_enter retried due to resource shortage\n",
323 	[KDBG_TRIAGE_VM_COMPRESSOR_GET_OUT_OF_RANGE] = "Compressor offset requested out of range\n",
324 	[KDBG_TRIAGE_VM_COMPRESSOR_GET_NO_PAGE] = "Compressor doesn't have this page\n",
325 	[KDBG_TRIAGE_VM_COMPRESSOR_DECOMPRESS_FAILED] = "Decompressor hit a failure\n",
326 	[KDBG_TRIAGE_VM_SUBMAP_NO_COW_ON_EXECUTABLE] = "Submap disallowed cow on executable range\n",
327 	[KDBG_TRIAGE_VM_SUBMAP_COPY_SLOWLY_FAILED] = "Submap object copy_slowly failed\n",
328 	[KDBG_TRIAGE_VM_SUBMAP_COPY_STRAT_FAILED] = "Submap object copy_strategically failed\n",
329 	[KDBG_TRIAGE_VM_VNODEPAGER_CLREAD_NO_UPL] = "vnode_pager_cluster_read couldn't create a UPL\n",
330 	[KDBG_TRIAGE_VM_VNODEPAGEIN_NO_UBCINFO] = "vnode_pagein got a vnode with no ubcinfo\n",
331 	[KDBG_TRIAGE_VM_VNODEPAGEIN_FSPAGEIN_FAIL] = "Filesystem pagein returned an error in vnode_pagein\n",
332 	[KDBG_TRIAGE_VM_VNODEPAGEIN_NO_UPL] = "vnode_pagein couldn't create a UPL\n",
333 	[KDBG_TRIAGE_VM_ECC_DIRTY] = "Accessed a page that has uncorrected ECC error\n",
334 	[KDBG_TRIAGE_VM_ECC_CLEAN] = "Clean page had an uncorrected ECC error\n",
335 	[KDBG_TRIAGE_VM_COPYOUTMAP_SAMEMAP_ERROR] = "vm_copyout_map failed with same src-dest map\n",
336 	[KDBG_TRIAGE_VM_COPYOUTMAP_DIFFERENTMAP_ERROR] = "vm_copyout_map failed with different src-dest map\n",
337 	[KDBG_TRIAGE_VM_COPYOVERWRITE_FULL_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying full copy\n",
338 	[KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying partial copy\n",
339 	[KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_HEAD_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying misaligned head copy\n",
340 	[KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_TAIL_NESTED_ERROR] = "vm_map_copy_overwrite_nested failed when trying misaligned tail copy\n",
341 	[KDBG_TRIAGE_VM_COPYOUT_INTERNAL_SIZE_ERROR] = "vm_map_copyout_internal failed due to bad size\n",
342 	[KDBG_TRIAGE_VM_COPYOUT_KERNEL_BUFFER_ERROR] = "vm_map_copyout_kernel_buffer failed\n",
343 	[KDBG_TRIAGE_VM_COPYOUT_INTERNAL_ADJUSTING_ERROR] = "vm_map_copyout_internal failed when trying to adjust src-dest params\n",
344 	[KDBG_TRIAGE_VM_COPYOUT_INTERNAL_SPACE_ERROR] = "vm_map_copyout_internal failed because we couldn't locate space\n",
345 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_BADFLAGS_ERROR] = "mach_vm_allocate_kernel failed due to bad flags\n",
346 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_BADMAP_ERROR] = "mach_vm_allocate_kernel failed due to bad map\n",
347 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_BADSIZE_ERROR] = "mach_vm_allocate_kernel failed due to bad size\n",
348 	[KDBG_TRIAGE_VM_ALLOCATE_KERNEL_VMMAPENTER_ERROR] = "mach_vm_allocate_kernel failed within call to vm_map_enter\n",
349 };
350 /* VM end */
351 
352 /* Cluster begin */
353 
354 const char *cluster_triage_strings[] =
355 {
356 	[KDBG_TRIAGE_CL_PREFIX] = "CL - ",
357 	[KDBG_TRIAGE_CL_PGIN_PAST_EOF] = "cluster_pagein past EOF\n",
358 };
359 /* Cluster end */
360 
361 /* Shared Region begin */
362 
363 const char *shared_region_triage_strings[] =
364 {
365 	[KDBG_TRIAGE_SHARED_REGION_PREFIX] = "SR - ",
366 	[KDBG_TRIAGE_SHARED_REGION_NO_UPL] = "shared_region_pager_data_request couldn't create a upl\n",
367 	[KDBG_TRIAGE_SHARED_REGION_SLIDE_ERROR] = "shared_region_pager_data_request hit a page sliding error\n",
368 	[KDBG_TRIAGE_SHARED_REGION_PAGER_MEMORY_SHORTAGE] = "shared_region_pager_data_request hit memory shortage\n",
369 };
370 /* Shared Region end */
371 
372 /* Dyld Pager begin */
373 
374 const char *dyld_pager_triage_strings[] =
375 {
376 	[KDBG_TRIAGE_DYLD_PAGER_PREFIX] = "DP - ",
377 	[KDBG_TRIAGE_DYLD_PAGER_NO_UPL] = "dyld_pager_data_request couldn't create a upl\n",
378 	[KDBG_TRIAGE_DYLD_PAGER_MEMORY_SHORTAGE] = "dyld_pager_data_request hit memory shortage\n",
379 	[KDBG_TRIAGE_DYLD_PAGER_SLIDE_ERROR] = "dyld_pager_data_request hit a page sliding error\n",
380 	[KDBG_TRIAGE_DYLD_PAGER_CHAIN_OUT_OF_RANGE] = "dyld_pager_data_request chain out of range\n",
381 	[KDBG_TRIAGE_DYLD_PAGER_SEG_INFO_OUT_OF_RANGE] = "dyld_pager_data_request seg_info out of range\n",
382 	[KDBG_TRIAGE_DYLD_PAGER_SEG_SIZE_OUT_OF_RANGE] = "dyld_pager_data_request seg->size out of range\n",
383 	[KDBG_TRIAGE_DYLD_PAGER_SEG_PAGE_CNT_OUT_OF_RANGE] = "dyld_pager_data_request seg->page_count out of range\n",
384 	[KDBG_TRIAGE_DYLD_PAGER_NO_SEG_FOR_VA] = "dyld_pager_data_request no segment for VA\n",
385 	[KDBG_TRIAGE_DYLD_PAGER_RANGE_NOT_FOUND] = "dyld_pager_data_request no range for offset\n",
386 	[KDBG_TRIAGE_DYLD_PAGER_DELTA_TOO_LARGE] = "dyld_pager_data_request delta * 4 > PAGE_SIZE\n",
387 	[KDBG_TRIAGE_DYLD_PAGER_PAGE_START_OUT_OF_RANGE] = "dyld_pager_data_request segInfo page_start out of range\n",
388 	[KDBG_TRIAGE_DYLD_PAGER_BAD_POINTER_FMT] = "dyld_pager_data_request unkown pointer format\n",
389 	[KDBG_TRIAGE_DYLD_PAGER_INVALID_AUTH_KEY] = "dyld_pager_data_request unkown auth key\n",
390 	[KDBG_TRIAGE_DYLD_PAGER_BIND_ORDINAL] = "dyld_pager_data_request invalid bind ordinal\n",
391 };
392 /* Dyld Pager end */
393 
394 /* Apple Protect Pager begin */
395 
396 const char *apple_protect_pager_triage_strings[] =
397 {
398 	[KDBG_TRIAGE_APPLE_PROTECT_PAGER_PREFIX] = "APP - ",
399 	[KDBG_TRIAGE_APPLE_PROTECT_PAGER_MEMORY_SHORTAGE] = "apple_protect_pager_data_request hit memory shortage\n",
400 };
401 /* Apple Protect Pager end */
402 
403 /* Corpse section begin */
404 
405 const char *corpse_triage_strings[] =
406 {
407 	[KDBG_TRIAGE_CORPSE_PREFIX] = "Corpse - ",
408 	[KDBG_TRIAGE_CORPSE_PROC_TOO_BIG] = "Process too big for corpse. Corpse disallowed.\n",
409 	[KDBG_TRIAGE_CORPSE_FAIL_LIBGMALLOC] = "Process linked against libgmalloc. Corpse disallowed.\n",
410 	[KDBG_TRIAGE_CORPSE_BLOCKED_JETSAM] = "Jetsams happening in higher bands. Corpse disallowed.\n",
411 	[KDBG_TRIAGE_CORPSE_LIMIT] = "Too many corpses in flight. Corpse disallowed.\n",
412 	[KDBG_TRIAGE_CORPSES_DISABLED] = "Corpse disabled on system.\n",
413 	[KDBG_TRIAGE_CORPSE_DISABLED_FOR_PROC] = "Corpse disabled for this process.\n",
414 };
415 /* Corpse section end */
416 
417 /* subsystems starts at index 1 */
418 ktriage_strings_t ktriage_subsystems_strings[KDBG_TRIAGE_SUBSYS_MAX + 1] = {
419 	/* Static subsystems */
420 	[KDBG_TRIAGE_SUBSYS_VM]            = {VM_MAX_TRIAGE_STRINGS, vm_triage_strings},
421 	[KDBG_TRIAGE_SUBSYS_CLUSTER]       = {CLUSTER_MAX_TRIAGE_STRINGS, cluster_triage_strings},
422 	[KDBG_TRIAGE_SUBSYS_SHARED_REGION] = {SHARED_REGION_MAX_TRIAGE_STRINGS, shared_region_triage_strings},
423 	[KDBG_TRIAGE_SUBSYS_DYLD_PAGER]    = {DYLD_PAGER_MAX_TRIAGE_STRINGS, dyld_pager_triage_strings},
424 	[KDBG_TRIAGE_SUBSYS_APPLE_PROTECT_PAGER] = {APPLE_PROTECT_PAGER_MAX_TRIAGE_STRINGS, apple_protect_pager_triage_strings},
425 	[KDBG_TRIAGE_SUBSYS_CORPSE]        = {CORPSE_MAX_TRIAGE_STRINGS, corpse_triage_strings},
426 
427 	/* Dynamic subsystems */
428 	[KDBG_TRIAGE_SUBSYS_APFS]          = {-1, NULL},
429 	[KDBG_TRIAGE_SUBSYS_DECMPFS]       = {-1, NULL},
430 	[KDBG_TRIAGE_SUBSYS_VM_SANITIZE]   = {-1, NULL},
431 };
432 
433 /* KDBG_TRIAGE_CODE_* section */
434