• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }