xref: /xnu-8796.101.5/osfmk/kern/backtrace.h (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
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