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