1 // Copyright (c) 2016-2021 Apple Inc. All rights reserved. 2 // 3 // @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 4 // 5 // This file contains Original Code and/or Modifications of Original Code 6 // as defined in and that are subject to the Apple Public Source License 7 // Version 2.0 (the 'License'). You may not use this file except in 8 // compliance with the License. The rights granted to you under the License 9 // may not be used to create, or enable the creation or redistribution of, 10 // unlawful or unlicensed copies of an Apple operating system, or to 11 // circumvent, violate, or enable the circumvention or violation of, any 12 // terms of an Apple operating system software license agreement. 13 // 14 // Please obtain a copy of the License at 15 // http://www.opensource.apple.com/apsl/ and read it before using this file. 16 // 17 // The Original Code and all software distributed under the License are 18 // distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 19 // EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 20 // INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 21 // FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 22 // Please see the License for the specific language governing rights and 23 // limitations under the License. 24 // 25 // @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 26 27 #ifndef KERN_BACKTRACE_H 28 #define KERN_BACKTRACE_H 29 30 // Kernel and user space backtracing (call stack walking) functions. 31 // 32 // For the current kernel stack, call backtrace from any context: 33 // 34 // ```c 35 // #define MAX_STK_LEN (8) 36 // 37 // void *ret_addrs[MAX_STK_LEN] = { 0 }; 38 // backtrace_info_t info = BTI_NONE; 39 // unsigned int stk_len = backtrace(ret_addrs, MAX_STK_LEN, NULL, &info); 40 // for (unsigned int i = 0; i < stk_len; i++) { 41 // printf("%p -> ", ret_addrs[i]); 42 // } 43 // printf("%s\n", (info & BTI_TRUNCATED) ? "TRUNC" : "NULL"); 44 // ``` 45 // 46 // For user stacks, call backtrace_user from a faultable context: 47 // 48 // ```c 49 // uintptr_t ret_addrs[MAX_STK_LEN] = { 0 }; 50 // struct backtrace_user_info info = BTUINFO_INIT; 51 // unsigned int stk_len = backtrace_user(ret_addrs, MAX_STK_LEN, NULL, &info); 52 // if (info.btui_error != 0) { 53 // printf("user space%s stack is %u frames deep\n", 54 // (info->btui_info & BTI_TRUNCATED) ? " truncated" : "", stk_len); 55 // } 56 // ``` 57 // 58 // Refer to documentation in backtrace(9) for more information. 59 60 #include <stdbool.h> 61 #include <stddef.h> 62 #include <stdint.h> 63 #include <sys/cdefs.h> 64 // XXX Surgically include just the errno_t definition, so this can still be used 65 // by Mach. 66 #include <sys/_types/_errno_t.h> 67 68 __BEGIN_DECLS 69 70 // backtrace_flags_t change how the backtraces are recorded. 71 __options_decl(backtrace_flags_t, uint32_t, { 72 BTF_NONE = 0x0, 73 // BTF_KERN_INTERRUPTED backtraces the interrupted kernel stack. 74 BTF_KERN_INTERRUPTED = 0x1, 75 }); 76 77 // The copy function is used to copy call stack frame and other information from 78 // the target call stack. If an error is returned, the backtrace is aborted. 79 typedef errno_t (*backtrace_user_copy_fn)(void *ctx, void *dst, user_addr_t src, 80 size_t size); 81 82 // This copy function returns an error when a copy attempt is made, effectively 83 // limiting the user backtrace to the PC. 84 errno_t backtrace_user_copy_error(void *ctx, void *dst, user_addr_t src, 85 size_t size); 86 87 // Parameters that control how the backtrace is taken. 88 struct backtrace_control { 89 backtrace_flags_t btc_flags; 90 // The frame address to start backtracing from; set to 0 to start from the 91 // calling frame. 92 uintptr_t btc_frame_addr; 93 // A thread to backtrace user stacks of; must be either the current thread 94 // or one which has been suspended. 95 void *btc_user_thread; 96 // A functions to call instead of the default copyin routine for 97 // user space backtracing. 98 backtrace_user_copy_fn btc_user_copy; 99 // A context to pass to the user copy routine. 100 void *btc_user_copy_context; 101 // Apply an offset to each address stored by the backtracer. 102 int64_t btc_addr_offset; 103 }; 104 105 // Use this offset when walking an async stack, so symbolicators that subtract 1 106 // from each address to find the call site see valid symbols, instead of 107 // whatever function is at a lower address than the function pointer. 108 #define BTCTL_ASYNC_ADDR_OFFSET ((int64_t)1) 109 110 #define BTCTL_INIT \ 111 ((struct backtrace_control){ \ 112 .btc_flags = BTF_NONE, \ 113 .btc_frame_addr = 0, \ 114 .btc_user_thread = NULL, \ 115 .btc_user_copy = NULL, \ 116 .btc_user_copy_context = NULL, \ 117 .btc_addr_offset = 0, \ 118 }) 119 120 // backtrace_info_t provides information about the backtrace. 121 __options_decl(backtrace_info_t, uint32_t, { 122 BTI_NONE = 0x0, 123 // BTI_64_BIT is set when the backtrace is made up of 64-bit addresses. 124 BTI_64_BIT = 0x1, 125 // BTI_TRUNCATED is set when the backtrace has been truncated, either due 126 // to an error copying data, an invalid frame pointer, or running out of 127 // buffer space. 128 BTI_TRUNCATED = 0x2, 129 }); 130 131 // Backtrace the current thread's kernel stack. 132 unsigned int backtrace(uintptr_t *bt, unsigned int btlen, 133 struct backtrace_control *ctl, backtrace_info_t *info_out) 134 __attribute__((noinline)); 135 136 // backtrace_pack_t changes the packing scheme for backtraces. 137 __enum_decl(backtrace_pack_t, uint32_t, { 138 // Leave the addresses alone. 139 BTP_NONE = 0x0, 140 // Subtract the kernel base address and store each offset in 4 bytes. 141 BTP_KERN_OFFSET_32 = 0x01, 142 }); 143 144 // Backtrace the current thread's kernel stack and store in a packed 145 // representation. 146 size_t backtrace_packed(backtrace_pack_t packing, uint8_t *bt, size_t btsize, 147 struct backtrace_control *ctl, backtrace_info_t *info_out) 148 __attribute__((noinline)); 149 150 // Convert an array of addresses to a packed representation. 151 size_t backtrace_pack(backtrace_pack_t packing, uint8_t *dst, 152 size_t dst_size, const uintptr_t *src, unsigned int src_len); 153 154 // Convert a packed backtrace to an array of addresses. 155 unsigned int backtrace_unpack(backtrace_pack_t packing, uintptr_t *dst, 156 unsigned int dst_len, const uint8_t *src, size_t src_size); 157 158 // backtrace_user_info describes a user backtrace. 159 struct backtrace_user_info { 160 backtrace_info_t btui_info; 161 errno_t btui_error; 162 // The index where the start of the async call stack was found. 163 unsigned int btui_async_start_index; 164 // The frame address that can be backtraced to follow the async call stack. 165 uintptr_t btui_async_frame_addr; 166 // The frame address to use to resume the backtrace when the call stack is 167 // truncated by the size of the passed-in buffer. 168 uintptr_t btui_next_frame_addr; 169 }; 170 171 #define BTUINFO_INIT \ 172 ((struct backtrace_user_info){ \ 173 .btui_error = 0, \ 174 .btui_info = BTI_NONE, \ 175 .btui_async_start_index = 0, \ 176 .btui_async_frame_addr = 0, \ 177 .btui_next_frame_addr = 0, \ 178 }) 179 180 // Backtrace a thread's user stack. 181 unsigned int backtrace_user(uintptr_t *bt, unsigned int btlen, 182 const struct backtrace_control *ctl, struct backtrace_user_info *info_out); 183 184 __END_DECLS 185 186 #endif // !defined(KERN_BACKTRACE_H) 187