1 /*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/dfx/stackinfo/tests/js_stackinfo_test.h"
17
unwind_user_finish(unwind_user_context_s * ctx)18 void unwind_user_finish(unwind_user_context_s *ctx) {}
19
mem_zero_s(unwind_stack_frame_s & frame)20 void mem_zero_s(unwind_stack_frame_s &frame)
21 {
22 frame.fp = 0;
23 frame.pc = 0;
24 }
25
is_entry_frame(unsigned int frame_type)26 bool is_entry_frame(unsigned int frame_type)
27 {
28 return is_frame_type(frame_type, FRAME_TYPE_MAX,
29 OPTIMIZED_ENTRY_FRAME,
30 ASM_INTERPRETER_ENTRY_FRAME);
31 }
32
is_js_function_frame(unsigned int frame_type)33 bool is_js_function_frame(unsigned int frame_type)
34 {
35 return is_frame_type(frame_type, FRAME_TYPE_MAX,
36 ASM_INTERPRETER_FRAME,
37 INTERPRETER_CONSTRUCTOR_FRAME,
38 INTERPRETER_FRAME,
39 INTERPRETER_FAST_NEW_FRAME);
40 }
41
is_native_function_frame(unsigned int frame_type)42 bool is_native_function_frame(unsigned int frame_type)
43 {
44 return is_frame_type(frame_type, FRAME_TYPE_MAX,
45 OPTIMIZED_FRAME,
46 BASELINE_BUILTIN_FRAME,
47 ASM_BRIDGE_FRAME,
48 OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
49 OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME,
50 OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME,
51 OPTIMIZED_JS_FUNCTION_FRAME,
52 LEAVE_FRAME,
53 LEAVE_FRAME_WITH_ARGV,
54 BUILTIN_CALL_LEAVE_FRAME,
55 BUILTIN_FRAME,
56 BUILTIN_ENTRY_FRAME,
57 BUILTIN_FRAME_WITH_ARGV,
58 BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME,
59 ASM_INTERPRETER_BRIDGE_FRAME);
60 }
61
calc_pc_addr_from_fp_addr(uintptr_t fp_addr,unsigned int frame_type)62 uintptr_t calc_pc_addr_from_fp_addr(uintptr_t fp_addr, unsigned int frame_type)
63 {
64 uintptr_t type_addr = fp_addr - sizeof(uintptr_t);
65 uintptr_t addr = type_addr - (uintptr_t)frame_offset_table64[frame_type].type_offset;
66 addr += (uintptr_t)frame_offset_table64[frame_type].pc_offset;
67 return addr;
68 }
69
calc_fp_addr_from_fp_addr(uintptr_t fp_addr,unsigned int frame_type)70 uintptr_t calc_fp_addr_from_fp_addr(uintptr_t fp_addr, unsigned int frame_type)
71 {
72 uintptr_t type_addr = fp_addr - sizeof(uintptr_t);
73 uintptr_t addr = type_addr - (uintptr_t)frame_offset_table64[frame_type].type_offset;
74 addr += (uintptr_t)frame_offset_table64[frame_type].fp_offset;
75 return addr;
76 }
77
clear_lazy_deopt_flag(uintptr_t frame_type_raw)78 uintptr_t clear_lazy_deopt_flag(uintptr_t frame_type_raw)
79 {
80 return (frame_type_raw & (uintptr_t)(~(1UL << LAZY_DEOPT_FLAG_BIT1)));
81 }
82
next_ark_frame(unwind_user_context_s * ctx,uintptr_t fp_addr,unsigned int curr_frame_type,unwind_stack_frame_s * frame,bool * ret_frame_avail)83 int next_ark_frame(unwind_user_context_s *ctx, uintptr_t fp_addr, unsigned int curr_frame_type,
84 unwind_stack_frame_s *frame, bool *ret_frame_avail)
85 {
86 int err = E_OK;
87 uintptr_t next_pc_addr = 0;
88 uintptr_t next_fp_addr = 0;
89 uintptr_t pc = 0UL;
90 uintptr_t fp = 0UL;
91
92 if (is_entry_frame(curr_frame_type)) {
93 next_fp_addr = fp_addr;
94 next_pc_addr = (uintptr_t)(fp_addr + sizeof(uintptr_t));
95 } else {
96 if (is_js_function_frame(curr_frame_type) || is_native_function_frame(curr_frame_type)) {
97 next_pc_addr = calc_pc_addr_from_fp_addr(fp_addr, curr_frame_type);
98 }
99 next_fp_addr = calc_fp_addr_from_fp_addr(fp_addr, curr_frame_type);
100 }
101 if (err == E_OK) {
102 if (next_fp_addr != 0UL) {
103 err = ctx->read_mem(ctx, next_fp_addr, &fp, sizeof(uintptr_t));
104 }
105 if (err == E_OK && next_pc_addr != 0UL) {
106 err = ctx->read_mem(ctx, next_pc_addr, &pc, sizeof(uintptr_t));
107 *ret_frame_avail = (err == E_OK);
108 }
109 frame->fp = fp;
110 frame->pc = pc;
111 }
112
113 return err;
114 }
115
next_ark_frame(unwind_user_context_s * ctx,uintptr_t fp_addr,unwind_stack_frame_s * frame,unsigned int * ret_frame_type)116 int next_ark_frame(unwind_user_context_s *ctx, uintptr_t fp_addr,
117 unwind_stack_frame_s *frame, unsigned int *ret_frame_type)
118 {
119 int err = E_OK;
120 uintptr_t frame_type = 0UL;
121 while (err == E_OK) {
122 bool frame_avail = false;
123 uintptr_t type_addr = (uintptr_t)(fp_addr - sizeof(uintptr_t));
124 err = ctx->read_mem(ctx, type_addr, &frame_type, sizeof(uintptr_t));
125 if (err == E_OK) {
126 frame_type = clear_lazy_deopt_flag(frame_type);
127 if (frame_type > BASELINE_BUILTIN_FRAME) {
128 err = E_INVAL;
129 break;
130 }
131 }
132 if (err == E_OK) {
133 err = next_ark_frame(ctx, fp_addr, (unsigned int)frame_type, frame, &frame_avail);
134 }
135 if (err == E_OK) {
136 fp_addr = frame->fp;
137 if (frame_avail) {
138 *ret_frame_type = (unsigned int)frame_type;
139 break;
140 }
141 }
142 }
143
144 return err;
145 }
146
step_ark_frame(unwind_user_context_s * ctx,const unwind_stack_frame_s * cur_frame)147 unwind_stack_frame_s step_ark_frame(unwind_user_context_s *ctx,
148 const unwind_stack_frame_s *cur_frame)
149 {
150 unsigned int frame_type = 0U;
151 unwind_stack_frame_s frame = UNWIND_FRAME_EMPTY;
152 int err = E_OK;
153
154 err = next_ark_frame(ctx, cur_frame->fp, &frame, &frame_type);
155 if (err == E_OK) {
156 if (is_entry_frame(frame_type) || !is_js_function_frame(frame_type)) {
157 unwind_user_finish(ctx);
158 }
159 }
160 if (err != E_OK) {
161 mem_zero_s(frame);
162 }
163 return frame;
164 }
165
unwind_arkts(unwind_user_context_s * context,const unwind_stack_frame_s * cur_frame)166 unwind_stack_frame_s unwind_arkts(unwind_user_context_s *context,
167 const unwind_stack_frame_s *cur_frame)
168 {
169 unwind_stack_frame_s frame = UNWIND_FRAME_EMPTY;
170 if (context != NULL && cur_frame != NULL) {
171 frame = step_ark_frame(context, cur_frame);
172 }
173 return frame;
174 }