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