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 #include <assert.h>
25 #include <kernel/usercopy.h>
26 #include <lib/backtrace/backtrace.h>
27 #include <stdbool.h>
28 #include <string.h>
29 #include <uapi/err.h>
30
31 /* Stack grows down */
32 const bool stack_direction = false;
33
34 /**
35 * struct user_stack_frame - user-space stack frame
36 * @fp: frame pointer
37 * @lr: link register
38 *
39 * If user-space is explicitly 32-bit (e.g. 64u32 configuration), use 32 bits
40 * for register values. Otherwise, assume same bitness as the kernel.
41 */
42 struct user_stack_frame {
43 #if USER_32BIT
44 uint32_t fp;
45 uint32_t lr;
46 #else
47 uintptr_t fp;
48 uintptr_t lr;
49 #endif
50 };
51
52 /**
53 * struct kernel_stack_frame - kernel-space stack frame
54 * @fp: frame pointer
55 * @lr: link register
56 */
57 struct kernel_stack_frame {
58 uintptr_t fp;
59 uintptr_t lr;
60 };
61
step_user_frame(struct stack_frame * frame)62 static int step_user_frame(struct stack_frame* frame) {
63 struct user_stack_frame uframe;
64 int rc = copy_from_user(&uframe, frame->fp, sizeof(uframe));
65 if (rc != NO_ERROR) {
66 return FRAME_CORRUPT;
67 }
68
69 frame->frame_addr = frame->fp;
70 frame->fp = uframe.fp;
71 frame->ret_addr = uframe.lr;
72 if (is_zero_frame(frame)) {
73 return FRAME_ZERO;
74 }
75 return FRAME_OK;
76 }
77
step_kernel_frame(struct stack_frame * frame,bool current_frame)78 static int step_kernel_frame(struct stack_frame* frame, bool current_frame) {
79 struct kernel_stack_frame kframe;
80 void* frame_addr = current_frame ? __GET_FRAME() : (void*)(frame->fp);
81 memcpy(&kframe, frame_addr, sizeof(kframe));
82
83 frame->frame_addr = (uintptr_t)frame_addr;
84 frame->fp = kframe.fp;
85 frame->ret_addr = kframe.lr;
86 if (is_zero_frame(frame)) {
87 return FRAME_ZERO;
88 }
89 return FRAME_OK;
90 }
91
step_frame(struct stack_frame * frame,bool user)92 int step_frame(struct stack_frame* frame, bool user) {
93 if (user) {
94 return step_user_frame(frame);
95 } else {
96 return step_kernel_frame(frame, false);
97 }
98 }
99
get_current_frame(struct stack_frame * frame)100 void get_current_frame(struct stack_frame* frame) {
101 step_kernel_frame(frame, true);
102 }
103