1 /* 2 * Copyright (c) 2021 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 #ifndef __KDP_COMMON_H 29 #define __KDP_COMMON_H 30 31 #ifdef XNU_KERNEL_PRIVATE 32 33 #include <kern/task.h> 34 #include <vm/vm_map.h> 35 36 /* 37 * Wrapper around memcpy. 38 * This copies individual bytes if running in the panic context. Otherwise, this 39 * calls the standard memcpy function. 40 */ 41 void kdp_memcpy(void *dst, const void *src, size_t len); 42 43 /* 44 * A version of strlcpy that is safe to run from the panic context. This calls 45 * kdp_memcpy() internally, which copies individual bytes if running in the panic context. 46 */ 47 size_t kdp_strlcpy(char *dst, const char *src, size_t maxlen); 48 49 /* 50 * Get the page size from the specified vm map. This correctly handles K16/U4 (Rosetta) and 51 * K4/U16 (armv7k) environments. 52 */ 53 size_t kdp_vm_map_get_page_size(vm_map_t map, size_t *effective_page_mask); 54 55 __options_closed_decl(kdp_fault_result_flags_t, uint32_t, { 56 KDP_FAULT_RESULT_PAGED_OUT = 0x1, /* some data was unable to be retrieved */ 57 KDP_FAULT_RESULT_TRIED_FAULT = 0x2, /* tried to fault in data */ 58 KDP_FAULT_RESULT_FAULTED_IN = 0x3, /* successfully faulted in data */ 59 }); 60 61 struct kdp_fault_result { 62 kdp_fault_result_flags_t flags; 63 uint64_t time_spent_faulting; 64 }; 65 66 __options_closed_decl(kdp_fault_flags_t, uint32_t, { 67 KDP_FAULT_FLAGS_NONE = 0x0, 68 KDP_FAULT_FLAGS_ENABLE_FAULTING = 0x1, /* try faulting if pages are not resident */ 69 }); 70 71 __options_closed_decl(kdp_traverse_mappings_flags_t, uint32_t, { 72 KDP_TRAVERSE_MAPPINGS_FLAGS_NONE = 0x0, 73 KDP_TRAVERSE_MAPPINGS_FLAGS_PHYSICAL = 0x1 /* Use physical addresses instead of virtual addresses */ 74 }); 75 76 typedef int (*kdp_traverse_mappings_callback)(vm_offset_t start, vm_offset_t end, void *context); 77 78 /* 79 * Traverse mappings in the specified task. 80 * 81 * - task The task 82 * - fault_flags Controls whether to fault in pages that are not resident. 83 * - traverse_mappings_flags Controls whether the callback is called with physical addresses 84 * - callback The callback is called for each memory region. 85 * - context Context passed to the callback. 86 */ 87 kern_return_t 88 kdp_traverse_mappings( 89 task_t task, 90 kdp_fault_flags_t fault_flags, 91 kdp_traverse_mappings_flags_t traverse_mappings_flags, 92 kdp_traverse_mappings_callback callback, 93 void * context); 94 95 /* 96 * Get dyld information from the specified task 97 * 98 * - task The task 99 * - fault_flags Controls whether to fault in pages that are not resident. 100 * - dyld_load_address The dyld load address is stored here. 101 * - dyld_uuid The dyld uuid is stored here. 102 * - task_page_size The task's page size is stored here. 103 */ 104 kern_return_t 105 kdp_task_dyld_info(task_t task, kdp_fault_flags_t fault_flags, uint64_t * dyld_load_address, uuid_t dyld_uuid, size_t * task_page_size); 106 107 /* 108 * Returns the physical address of the specified map:target address, 109 * using the kdp fault path if requested and the page is not resident. 110 */ 111 vm_offset_t kdp_find_phys(vm_map_t map, vm_offset_t target_addr, kdp_fault_flags_t fault_flags, struct kdp_fault_result *fault_results); 112 113 /* 114 * Generic function to find a physical page for the specified map:target_addr. 115 */ 116 typedef vm_offset_t (*find_phys_fn_t)(vm_map_t map, vm_offset_t target_addr, kdp_fault_flags_t fault_flags, void * context); 117 118 /* 119 * Generic copyin from userspace vm map. 120 * 121 * - map The vm map to use 122 * - uaddr Userspace VA to copy bytes from 123 * - dest Destination address 124 * - size Number of bytes to copy 125 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn`. 126 * - find_phys_fn The function to use to return a physical address given a map and target address. 127 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys` 128 * for this parameter. 129 * - context Reference context passed to find_phys_fn 130 * 131 * Copies in `size` bytes from `map:uaddr` to `dest`, using the specified function to find a physical address. 132 * Returns 0 if successful, an errno otherwise. 133 */ 134 int kdp_generic_copyin(vm_map_t map, uint64_t uaddr, void *dest, size_t size, kdp_fault_flags_t fault_flags, find_phys_fn_t find_phys_fn, void *context); 135 136 /* 137 * Copies in a word from the specified task and address. 138 * 139 * - task The task to use 140 * - addr Address to copy from 141 * - result Where to store result 142 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn` 143 * - find_phys_fn The function to use to return a physical address given a map and target address. 144 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys` 145 * for this parameter. 146 * - context Reference context passed to find_phys_fn 147 * 148 * Returns 0 if successful, an errno otherwise. 149 */ 150 int kdp_generic_copyin_word(task_t task, uint64_t addr, uint64_t *result, kdp_fault_flags_t fault_flags, find_phys_fn_t find_phys_fn, void *context); 151 152 /* 153 * Copies in a string from the specified task and address. 154 * 155 * - task The task to use 156 * - addr Address to copy from 157 * - buf Where to store result 158 * - buf_sz Size of destination buffer 159 * - fault_flags Controls whether to fault in pages that are not resident. This is passed to `find_phys_fn` 160 * - find_phys_fn The function to use to return a physical address given a map and target address. 161 * If additional filtering/handling is not required, use `(find_phys_fn_t)kdp_find_phys` 162 * for this parameter. 163 * - context Reference context passed to find_phys_fn 164 * 165 * Returns number of bytes copied if successful, -1 otherwise. 166 */ 167 int kdp_generic_copyin_string(task_t task, uint64_t addr, char *buf, int buf_sz, kdp_fault_flags_t fault_flags, find_phys_fn_t find_phys_fn, void *context); 168 169 #endif /* XNU_KERNEL_PRIVATE */ 170 171 #endif /* __KDP_COMMON_H */ 172