1 /*
2  * Copyright (c) 2020 Google Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #pragma once
25 
26 #ifdef LIB_BACKTRACE_ENABLE
27 #include <kernel/thread.h>
28 
29 /**
30  * stack_direction - direction of stack growth
31  *
32  * Stack direction is arch-specific. False if stack grows downwards (i.e.
33  * towards 0), true otherwise.
34  */
35 extern const bool stack_direction;
36 
37 /**
38  * struct stack_frame - stack frame of a function call
39  * @frame_addr: address of the current frame on the stack
40  * @fp: pointer to previous frame on the stack
41  * @ret_addr: return address
42  *
43  * There is more stuff in the frame record. However, for the purpose of
44  * backtracing we only need frame pointer and return address.
45  */
46 struct stack_frame {
47     uintptr_t frame_addr;
48     uintptr_t fp;
49     uintptr_t ret_addr;
50 };
51 
is_zero_frame(struct stack_frame * frame)52 static inline bool is_zero_frame(struct stack_frame* frame) {
53     return !frame->fp;
54 }
55 
56 enum frame_state {
57     FRAME_OK,
58     FRAME_ZERO,
59     FRAME_CORRUPT,
60     FRAME_NON_MONOTONIC,
61 };
62 
63 /**
64  * get_current_frame() - get current stack frame
65  * @frame: current frame will be copied into @frame
66  */
67 void get_current_frame(struct stack_frame* frame);
68 
69 /**
70  * step_frame() - get next stack frame
71  * @frame: current frame, next frame will written in-place
72  * @user: true if we're traversing a user stack, false if kernel stack
73  *
74  * Return: frame_state, state of the next frame
75  */
76 int step_frame(struct stack_frame* frame, bool user);
77 
78 /**
79  * dump_thread_backtrace() - dump backtrace of a given thread
80  * @thread: thread being backtraced
81  */
82 void dump_thread_backtrace(struct thread* thread);
83 
84 /**
85  * dump_backtrace() - dump backtrace from current location
86  */
dump_backtrace(void)87 static inline void dump_backtrace(void) {
88     dump_thread_backtrace(get_current_thread());
89 }
90 #else
dump_backtrace(void)91 static void dump_backtrace(void) {}
92 #endif
93