Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "stacktrace_unwind_instr.h"
12 : #include <stdlib.h>
13 : #include <pthread.h>
14 : #include <fcntl.h>
15 : #include <string.h>
16 : #include <link.h>
17 : #include "stacktrace_unwind.h"
18 : #include "stacktrace_unwind_inner.h"
19 : #include "stacktrace_fp.h"
20 : #include "stacktrace_signal.h"
21 : #include "stddef.h"
22 : #include "securec.h"
23 : #include "trace_system_api.h"
24 : #include "adiag_utils.h"
25 : #include "adiag_print.h"
26 : #include "scd_log.h"
27 : #include "scd_dwarf.h"
28 :
29 : #define VOS_OP_DATA_TYPE_UINT8 1
30 : #define VOS_OP_DATA_TYPE_UINT16 2
31 : #define VOS_OP_DATA_TYPE_UINT32 4
32 : #define VOS_OP_DATA_TYPE_UINT64 8
33 :
34 : /**
35 : * @brief 解析栈操作类指令中的其他类型操作
36 : *
37 : * @param [in] opType 操作类型
38 : * @param [in] stackContent 操作栈内容
39 : * @param [in] idx 操作栈索引
40 : * @param [in] insAddr 指令地址
41 : * @param [in] coreRegs 核心寄存器数组
42 : * @param [out] result 操作结果
43 : *
44 : * @return 指令地址
45 : */
46 126 : STATIC const uint8_t* TraceOpStackOtherOpt(
47 : ScdDwarf* dwarf, uint8_t opType, const uintptr_t stackContent[VOS_OP_STACK_DEPTH], uint32_t* idx,
48 : const uint8_t* insAddr, const ScdRegs* coreRegs, uintptr_t* result)
49 : {
50 : uintptr_t regData;
51 : uintptr_t resTmp;
52 : intptr_t psvVal;
53 : uint16_t offset;
54 126 : const uint8_t* insAddrTmp = insAddr;
55 126 : uintptr_t tmpRes = 0;
56 126 : uint32_t tmpIdx = *idx;
57 :
58 126 : switch (opType) {
59 18 : case DW_OP_REGX:
60 18 : insAddrTmp = TraceReadUleb128(dwarf, insAddrTmp, ®Data);
61 18 : SCD_CHK_EXPR_ACTION(insAddrTmp == NULL, return NULL, "read uleb128 failed");
62 18 : tmpRes = (uintptr_t)coreRegs->r[regData & REG_VAILD_MASK];
63 18 : break;
64 18 : case DW_OP_BREGX:
65 18 : insAddrTmp = TraceReadUleb128(dwarf, insAddrTmp, ®Data);
66 18 : SCD_CHK_EXPR_ACTION(insAddrTmp == NULL, return NULL, "read uleb128 failed");
67 18 : insAddrTmp = TraceReadLeb128(dwarf, insAddrTmp, &psvVal);
68 18 : SCD_CHK_EXPR_ACTION(insAddrTmp == NULL, return NULL, "read leb128 failed");
69 18 : tmpRes = coreRegs->r[regData & REG_VAILD_MASK] + (uintptr_t)psvVal;
70 18 : break;
71 : /* 无编码类型的地址 */
72 18 : case DW_OP_ADDR:
73 18 : tmpRes = TraceReadUintptr(insAddrTmp, sizeof(uintptr_t));
74 18 : insAddrTmp = insAddrTmp + sizeof(void*);
75 18 : break;
76 18 : case DW_OP_GNU_ENC_ADDR:
77 : /* 该地址第一个字节表示编码类型,从第二字节开始才表示该编码类型时的数据 */
78 18 : insAddrTmp = TraceReadEncodeValue(dwarf, *insAddrTmp, insAddrTmp + 1, &resTmp);
79 18 : tmpRes = resTmp;
80 18 : break;
81 : /* dw_op指令跳转 */
82 18 : case DW_OP_SKIP:
83 18 : offset = TraceReadU16(insAddrTmp, sizeof(uint16_t));
84 18 : insAddrTmp += sizeof(uint16_t);
85 18 : insAddrTmp += offset;
86 18 : break;
87 : /* dw_op指令依条件跳转 */
88 18 : case DW_OP_BRA:
89 18 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 1U, { return NULL; });
90 18 : tmpIdx = tmpIdx - 1U;
91 18 : offset = TraceReadU16(insAddrTmp, sizeof(uint16_t));
92 18 : insAddrTmp += sizeof(uint16_t);
93 18 : if (stackContent[(tmpIdx & VOS_OP_STACK_MASK)] != 0) {
94 18 : insAddrTmp += offset;
95 : }
96 18 : break;
97 18 : case DW_OP_NOP:
98 : default:
99 18 : break;
100 : }
101 126 : *result = tmpRes;
102 126 : *idx = tmpIdx;
103 126 : return insAddrTmp;
104 : }
105 :
106 : /**
107 : * @brief 解析栈操作类指令中两个操作数的高级操作
108 : *
109 : * @param [in] opType 操作类型
110 : * @param [in] swapTmp1 栈数据1
111 : * @param [in] swapTmp2 栈数据2
112 : * @param [out] result 操作结果
113 : *
114 : * @return 指令地址
115 : */
116 360 : STATIC void TraceOpStackTwoDataParseAdvanced(uint8_t opType, uintptr_t swapTmp1, uintptr_t swapTmp2, uintptr_t* result)
117 : {
118 360 : uintptr_t tmpRes = 0;
119 :
120 360 : switch (opType) {
121 36 : case DW_OP_SHL:
122 36 : tmpRes = (uintptr_t)(swapTmp1 << swapTmp2);
123 36 : break;
124 72 : case DW_OP_SHR:
125 : case DW_OP_SHRA:
126 72 : tmpRes = (uintptr_t)(swapTmp1 >> swapTmp2);
127 72 : break;
128 36 : case DW_OP_XOR:
129 36 : tmpRes = (uintptr_t)(swapTmp1 ^ swapTmp2);
130 36 : break;
131 36 : case DW_OP_LE:
132 36 : tmpRes = (uintptr_t)(swapTmp1 <= swapTmp2);
133 36 : break;
134 36 : case DW_OP_GE:
135 36 : tmpRes = (uintptr_t)(swapTmp1 >= swapTmp2);
136 36 : break;
137 36 : case DW_OP_EQ:
138 36 : tmpRes = (uintptr_t)(swapTmp1 == swapTmp2);
139 36 : break;
140 36 : case DW_OP_LT:
141 36 : tmpRes = (uintptr_t)(swapTmp1 < swapTmp2);
142 36 : break;
143 36 : case DW_OP_GT:
144 36 : tmpRes = (uintptr_t)(swapTmp1 > swapTmp2);
145 36 : break;
146 36 : case DW_OP_NE:
147 36 : tmpRes = (uintptr_t)(swapTmp1 != swapTmp2);
148 36 : break;
149 0 : default:
150 0 : break; // will never be executed
151 : }
152 360 : *result = tmpRes;
153 360 : return;
154 : }
155 :
156 : /**
157 : * @brief 解析栈操作类指令中两个操作数的基础操作
158 : *
159 : * @param [in] opType 操作类型
160 : * @param [in] swapTmp1 栈数据1
161 : * @param [in] swapTmp2 栈数据2
162 : * @param [out] result 操作结果
163 : *
164 : * @return 指令地址
165 : */
166 : STATIC TraStatus
167 270 : TraceOpStackTwoDataParseBasic(uint8_t opType, uintptr_t swapTmp1, uintptr_t swapTmp2, uintptr_t* result)
168 : {
169 270 : uintptr_t tmpRes = 0;
170 270 : TraStatus ret = TRACE_SUCCESS;
171 :
172 270 : switch (opType) {
173 36 : case DW_OP_AND:
174 36 : tmpRes = swapTmp1 & swapTmp2;
175 36 : break;
176 36 : case DW_OP_DIV:
177 36 : if (swapTmp2 == 0) {
178 18 : return TRACE_FAILURE;
179 : }
180 18 : tmpRes = swapTmp1 / swapTmp2;
181 18 : break;
182 :
183 36 : case DW_OP_MINUS:
184 36 : tmpRes = (uintptr_t)(swapTmp1 - swapTmp2);
185 36 : break;
186 36 : case DW_OP_MOD:
187 36 : if (swapTmp2 == 0) {
188 18 : return TRACE_FAILURE;
189 : }
190 18 : tmpRes = (uintptr_t)(swapTmp1 % swapTmp2);
191 18 : break;
192 36 : case DW_OP_MUL:
193 36 : tmpRes = (uintptr_t)(swapTmp1 * swapTmp2);
194 36 : break;
195 36 : case DW_OP_OR:
196 36 : tmpRes = (uintptr_t)(swapTmp1 | swapTmp2);
197 36 : break;
198 36 : case DW_OP_PLUS:
199 36 : tmpRes = (uintptr_t)(swapTmp1 + swapTmp2);
200 36 : break;
201 18 : default:
202 18 : ret = TRACE_FAILURE;
203 18 : break; // will never be executed
204 : }
205 234 : *result = tmpRes;
206 234 : return ret;
207 : }
208 :
209 : /**
210 : * @brief 解析栈操作类指令中两个操作数的操作
211 : *
212 : * @param [in] opType 操作类型
213 : * @param [in] swapTmp1 栈数据1
214 : * @param [in] swapTmp2 栈数据2
215 : * @param [out] result 操作结果
216 : *
217 : * @return 指令地址
218 : */
219 612 : STATIC TraStatus TraceOpStackTwoDataParse(uint8_t opType, uintptr_t swapTmp1, uintptr_t swapTmp2, uintptr_t* result)
220 : {
221 612 : uintptr_t tmpRes = 0;
222 : TraStatus ret;
223 :
224 612 : if (VOS_ENC_OP_TWO_DATA1(opType)) {
225 252 : ret = TraceOpStackTwoDataParseBasic(opType, swapTmp1, swapTmp2, &tmpRes);
226 252 : if (ret != TRACE_SUCCESS) {
227 36 : return ret;
228 : }
229 360 : } else if (VOS_ENC_OP_TWO_DATA2(opType)) {
230 360 : TraceOpStackTwoDataParseAdvanced(opType, swapTmp1, swapTmp2, &tmpRes);
231 : } else {
232 0 : return TRACE_FAILURE;
233 : }
234 576 : *result = tmpRes;
235 576 : return TRACE_SUCCESS;
236 : }
237 :
238 : /**
239 : * @brief 处理栈操作类指令中两个操作数的操作
240 : *
241 : * @param [in] opType 操作类型
242 : * @param [in] stackContent 栈信息
243 : * @param [in] idx 栈索引
244 : * @param [out] result 操作结果
245 : *
246 : * @return 指令地址
247 : */
248 : STATIC TraStatus
249 5076 : TraceOpStackTwoDataOpt(uint8_t opType, uintptr_t stackContent[VOS_OP_STACK_DEPTH], uint32_t* idx, uintptr_t* result)
250 : {
251 : uintptr_t swapTmp1;
252 : uintptr_t swapTmp2;
253 5076 : uintptr_t tmpRes = 0;
254 5076 : TraStatus ret = TRACE_SUCCESS;
255 5076 : uint32_t tmpIdx = *idx;
256 :
257 5076 : switch (opType) {
258 : /* 逻辑处理 */
259 630 : case DW_OP_AND:
260 : case DW_OP_DIV:
261 : case DW_OP_MINUS:
262 : case DW_OP_MOD:
263 : case DW_OP_MUL:
264 : case DW_OP_OR:
265 : case DW_OP_PLUS:
266 : case DW_OP_SHL:
267 : case DW_OP_SHR:
268 : case DW_OP_SHRA:
269 : case DW_OP_XOR:
270 : case DW_OP_LE:
271 : case DW_OP_GE:
272 : case DW_OP_EQ:
273 : case DW_OP_LT:
274 : case DW_OP_GT:
275 : case DW_OP_NE:
276 630 : if (tmpIdx < 2) { /* 2保证数组下标不为负数 */
277 18 : return TRACE_FAILURE;
278 : }
279 612 : swapTmp1 = stackContent[(tmpIdx - 2U) & VOS_OP_STACK_MASK]; /* 2是偏移量 */
280 612 : swapTmp2 = stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK];
281 612 : tmpIdx = tmpIdx - 2U; /* 2是偏移量 */
282 612 : ret = TraceOpStackTwoDataParse(opType, swapTmp1, swapTmp2, &tmpRes);
283 612 : break;
284 4446 : default:
285 4446 : ret = TRACE_FAILURE;
286 4446 : break;
287 : }
288 5058 : *result = tmpRes;
289 5058 : *idx = tmpIdx;
290 5058 : return ret;
291 : }
292 :
293 90 : STATIC TraStatus TraceDefSizeGet(const uint8_t ucEncode, uintptr_t pDataAddr, uintptr_t* result)
294 : {
295 90 : uintptr_t tmpRes = 0;
296 90 : TraStatus ret = TRACE_SUCCESS;
297 90 : switch (ucEncode) {
298 18 : case VOS_OP_DATA_TYPE_UINT8:
299 18 : tmpRes = (uintptr_t)(*(uint8_t*)pDataAddr);
300 18 : break;
301 18 : case VOS_OP_DATA_TYPE_UINT16:
302 18 : tmpRes = (uintptr_t)(*(uint16_t*)pDataAddr);
303 18 : break;
304 18 : case VOS_OP_DATA_TYPE_UINT32:
305 18 : tmpRes = (uintptr_t)(*(uint32_t*)pDataAddr);
306 18 : break;
307 18 : case VOS_OP_DATA_TYPE_UINT64:
308 18 : tmpRes = (uintptr_t)(*(uint64_t*)pDataAddr);
309 18 : break;
310 18 : default:
311 18 : ret = TRACE_FAILURE;
312 18 : break;
313 : }
314 90 : *result = tmpRes;
315 90 : return ret;
316 : }
317 :
318 : /**
319 : * @brief 解析栈操作类指令中一个操作数的操作
320 : *
321 : * @param [in] opType 操作类型
322 : * @param [in] tmpRes 栈数据
323 : * @param [in] insAddr 指令地址
324 : * @param [in] pstStackLimit 栈地址限制
325 : * @param [out] result 操作结果
326 : *
327 : * @return 指令地址
328 : */
329 234 : STATIC const uint8_t* TraceOpStackOneDataParse(
330 : ScdDwarf* dwarf, uint8_t opType, uintptr_t tmpRes, const uint8_t* insAddr, const ScdDwarfStepArgs* args,
331 : uintptr_t* result)
332 : {
333 : uintptr_t tmp;
334 234 : uintptr_t res = 0;
335 : intptr_t tmpSignedValue;
336 : TraStatus ret;
337 234 : const uint8_t* insAddrTmp = insAddr;
338 :
339 234 : switch (opType) {
340 36 : case DW_OP_DEREF:
341 36 : if (TRACE_STACK_ADDR_INVALID_CHECK(args, tmpRes)) {
342 18 : return NULL;
343 : }
344 : /* ScdMemoryRead(NULL, ...) uses global handler (ScdMemoryRemoteRead via ptrace).
345 : * Safe here: this function is only called from dumper subprocess context
346 : * (ScdProcessDump -> ScdDwarfStep -> TraceStackOpExc), where ptrace is available. */
347 18 : size_t size = ScdMemoryRead(NULL, tmpRes, &res, sizeof(uintptr_t));
348 18 : SCD_CHK_EXPR_ACTION(size == 0, return NULL, "scd read memory failed 0x%llx", tmpRes);
349 18 : break;
350 : /* 根据地址所指类型取值,注意地址合法性 */
351 108 : case DW_OP_DEREF_SIZE:
352 108 : if (TRACE_STACK_ADDR_INVALID_CHECK(args, tmpRes)) {
353 18 : return NULL;
354 : }
355 90 : ret = TraceDefSizeGet(*insAddrTmp, tmpRes, &res);
356 90 : insAddrTmp++;
357 90 : if (ret != TRACE_SUCCESS) {
358 18 : return NULL;
359 : }
360 72 : break;
361 18 : case DW_OP_ABS:
362 18 : tmpSignedValue = (intptr_t)tmpRes;
363 18 : if (tmpSignedValue < 0) {
364 18 : tmpSignedValue = -tmpSignedValue;
365 : }
366 18 : res = (uintptr_t)tmpSignedValue;
367 18 : break;
368 18 : case DW_OP_NEG:
369 18 : tmpSignedValue = (intptr_t)tmpRes;
370 18 : tmpSignedValue = -tmpSignedValue;
371 18 : res = (uintptr_t)tmpSignedValue;
372 18 : break;
373 18 : case DW_OP_NOT:
374 18 : res = ~tmpRes;
375 18 : break;
376 : /* 数据相加一常数 */
377 18 : case DW_OP_PLUS_UCONST:
378 18 : insAddrTmp = TraceReadUleb128(dwarf, insAddrTmp, &tmp);
379 18 : SCD_CHK_EXPR_ACTION(insAddrTmp == NULL, return NULL, "read uleb128 failed");
380 18 : res = tmp + tmpRes;
381 18 : break;
382 18 : default:
383 18 : insAddrTmp = NULL;
384 18 : break; // will never be executed
385 : }
386 180 : *result = res;
387 180 : return insAddrTmp;
388 : }
389 :
390 : /**
391 : * @brief 处理栈操作类指令中一个操作数的操作
392 : *
393 : * @param [in] opType 操作类型
394 : * @param [in] stackContent 栈数据
395 : * @param [in] idx 栈索引
396 : * @param [in] insAddr 指令地址
397 : * @param [in] pstStackLimit 栈地址限制
398 : * @param [out] result 操作结果
399 : *
400 : * @return 指令地址
401 : */
402 234 : STATIC const uint8_t* TraceOpStackOneDataOpt(
403 : ScdDwarf* dwarf, uint8_t opType, uintptr_t stackContent[VOS_OP_STACK_DEPTH], uint32_t* idx, const uint8_t* insAddr,
404 : const ScdDwarfStepArgs* args, uintptr_t* result)
405 : {
406 : uintptr_t indircRes;
407 234 : uintptr_t dircRes = 0;
408 234 : uint32_t tmpIdx = *idx;
409 234 : const uint8_t* insAddrTmp = insAddr;
410 :
411 234 : switch (opType) {
412 216 : case DW_OP_DEREF:
413 : case DW_OP_DEREF_SIZE:
414 : case DW_OP_ABS:
415 : case DW_OP_NEG:
416 : case DW_OP_NOT:
417 : case DW_OP_PLUS_UCONST:
418 216 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 1U, { return NULL; });
419 216 : indircRes = stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK];
420 216 : tmpIdx = tmpIdx - 1U;
421 216 : insAddrTmp = TraceOpStackOneDataParse(dwarf, opType, indircRes, insAddrTmp, args, &dircRes);
422 216 : TRACE_UNWIND_PARSE_ADDR_CHECK_OR_RETURN(insAddrTmp);
423 162 : break;
424 18 : default:
425 18 : insAddrTmp = NULL;
426 18 : break;
427 : }
428 :
429 180 : *result = dircRes;
430 180 : *idx = tmpIdx;
431 :
432 180 : return insAddrTmp;
433 : }
434 :
435 : /**
436 : * @brief 处理栈操作类指令
437 : *
438 : * @param [in] opType 操作类型
439 : * @param [in] stackContent 栈数据
440 : * @param [in] idx 栈索引
441 : * @param [in] insAddr 指令地址
442 : * @param [out] result 操作结果
443 : *
444 : * @return 指令地址
445 : */
446 648 : STATIC const uint8_t* TraceOpStackDataOpt(
447 : uint8_t opType, uintptr_t stackContent[VOS_OP_STACK_DEPTH], uint32_t* idx, const uint8_t* insAddr,
448 : uintptr_t* result)
449 : {
450 : uintptr_t swapTmp, swapTmp1, swapTmp2, swapTmp3;
451 : uint32_t offset;
452 648 : const uint8_t* insAddrTmp = insAddr;
453 648 : uintptr_t tmpRes = 0;
454 648 : uint32_t tmpIdx = *idx;
455 :
456 648 : switch (opType) {
457 : /* 在栈顶复制一份数据 */
458 360 : case DW_OP_DUP:
459 360 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 1U, { return NULL; });
460 360 : tmpRes = stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK];
461 360 : break;
462 : /* 栈顶弹出数据 */
463 108 : case DW_OP_DROP:
464 108 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 1U, { return NULL; });
465 90 : tmpRes = stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK];
466 90 : tmpIdx = tmpIdx - 1U;
467 90 : break;
468 : /* 从栈中间获取一数据 */
469 54 : case DW_OP_PICK:
470 54 : offset = (uint32_t)(*(uint8_t*)(uintptr_t)insAddrTmp);
471 54 : insAddrTmp++;
472 54 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, offset + 2U, { return NULL; });
473 36 : tmpRes = stackContent[(tmpIdx - offset - 1U) & VOS_OP_STACK_MASK];
474 36 : break;
475 : /* 从栈顶的一层取数据 */
476 36 : case DW_OP_OVER:
477 36 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 2U, { return NULL; });
478 18 : tmpRes = stackContent[(tmpIdx - 2U) & VOS_OP_STACK_MASK]; /* 2表示偏移 */
479 18 : break;
480 : /* 交换数据 */
481 36 : case DW_OP_SWAP:
482 36 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 2U, { return NULL; });
483 18 : swapTmp = stackContent[(tmpIdx - 2U) & VOS_OP_STACK_MASK]; /* 2表示偏移 */
484 : /* 2表示偏移 */
485 18 : stackContent[(tmpIdx - 2U) & VOS_OP_STACK_MASK] = stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK];
486 18 : stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK] = swapTmp;
487 18 : break;
488 36 : case DW_OP_ROT:
489 36 : TRACE_STACK_INDEX_CHECK_RET(tmpIdx, 3U, { return NULL; });
490 18 : swapTmp1 = stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK];
491 18 : swapTmp2 = stackContent[(tmpIdx - 2U) & VOS_OP_STACK_MASK]; /* 2表示偏移 */
492 18 : swapTmp3 = stackContent[(tmpIdx - 3U) & VOS_OP_STACK_MASK]; /* 3表示偏移 */
493 18 : stackContent[(tmpIdx - 1U) & VOS_OP_STACK_MASK] = swapTmp2;
494 18 : stackContent[(tmpIdx - 2U) & VOS_OP_STACK_MASK] = swapTmp3; /* 2表示偏移 */
495 18 : stackContent[(tmpIdx - 3U) & VOS_OP_STACK_MASK] = swapTmp1; /* 3表示偏移 */
496 18 : break;
497 18 : default:
498 18 : insAddrTmp = NULL;
499 18 : break; // will never be executed
500 : }
501 558 : *idx = tmpIdx;
502 558 : *result = tmpRes;
503 558 : return insAddrTmp;
504 : }
505 :
506 : /**
507 : * @brief 根据操作类型获取常数操作数
508 : *
509 : * @param [in] opType 操作类型
510 : * @param [in] insAddr 指令地址
511 : * @param [out] result 操作结果
512 : *
513 : * @return 指令地址
514 : */
515 198 : STATIC const uint8_t* TraceOpConstNumGet(ScdDwarf* dwarf, uint8_t opType, const uint8_t* insAddr, uintptr_t* result)
516 : {
517 : uintptr_t tmp;
518 : intptr_t tmpSignedValue;
519 198 : const uint8_t* insAddrTmp = insAddr;
520 198 : uintptr_t* resultTmp = result;
521 :
522 198 : switch (opType) {
523 18 : case DW_OP_COUST1U:
524 18 : *resultTmp = (uintptr_t)(*(uint8_t*)(uintptr_t)insAddrTmp);
525 18 : insAddrTmp += sizeof(uint8_t);
526 18 : break;
527 18 : case DW_OP_COUST1S:
528 18 : *resultTmp = (uintptr_t)(*(int8_t*)(uintptr_t)insAddrTmp);
529 18 : insAddrTmp += sizeof(int8_t);
530 18 : break;
531 18 : case DW_OP_COUST2U:
532 18 : *resultTmp = (uintptr_t)TraceReadU16(insAddrTmp, sizeof(uint16_t));
533 18 : insAddrTmp += sizeof(uint16_t);
534 18 : break;
535 18 : case DW_OP_COUST2S:
536 18 : *resultTmp = (uintptr_t)TraceReadS16(insAddrTmp, sizeof(int16_t));
537 18 : insAddrTmp += sizeof(int16_t);
538 18 : break;
539 18 : case DW_OP_COUST4U:
540 18 : *resultTmp = (uintptr_t)TraceReadU32(insAddrTmp, sizeof(uint32_t));
541 18 : insAddrTmp += sizeof(uint32_t);
542 18 : break;
543 18 : case DW_OP_COUST4S:
544 18 : *resultTmp = (uintptr_t)TraceReadS32(insAddrTmp, sizeof(int32_t));
545 18 : insAddrTmp += sizeof(int32_t);
546 18 : break;
547 18 : case DW_OP_COUST8U:
548 18 : *resultTmp = (uintptr_t)TraceReadU64(insAddrTmp, sizeof(uint64_t));
549 18 : insAddrTmp += sizeof(uint64_t);
550 18 : break;
551 18 : case DW_OP_COUST8S:
552 18 : *resultTmp = (uintptr_t)TraceReadS64(insAddrTmp, sizeof(int64_t));
553 18 : insAddrTmp += sizeof(int64_t);
554 18 : break;
555 18 : case DW_OP_COUSTU:
556 18 : insAddrTmp = TraceReadUleb128(dwarf, insAddrTmp, &tmp);
557 18 : SCD_CHK_EXPR_ACTION(insAddrTmp == NULL, return NULL, "read uleb128 failed");
558 18 : *resultTmp = (uintptr_t)tmp;
559 18 : break;
560 18 : case DW_OP_COUSTS:
561 18 : insAddrTmp = TraceReadLeb128(dwarf, insAddrTmp, &tmpSignedValue);
562 18 : SCD_CHK_EXPR_ACTION(insAddrTmp == NULL, return NULL, "read leb128 failed");
563 18 : *resultTmp = (uintptr_t)tmpSignedValue;
564 18 : break;
565 18 : default:
566 18 : *resultTmp = 0;
567 18 : insAddrTmp = NULL;
568 18 : break; // will never be executed
569 : }
570 198 : return insAddrTmp;
571 : }
572 :
573 : /**
574 : * @brief 解析操作码
575 : *
576 : * @param [in] opType 操作类型
577 : * @param [in] instr 指令地址
578 : * @param [out] pstFrameRInfo 推栈状态信息结构体
579 : *
580 : * @return 指令地址
581 : */
582 72 : STATIC const uint8_t* TraceUnwindOpcodeParse(
583 : ScdDwarf* dwarf, uint8_t opcode, const uint8_t* instr, TraceFrameRegStateInfo* pstFrameRInfo)
584 : {
585 : uintptr_t offsetTemp;
586 : intptr_t offset;
587 72 : const uint8_t* tmpInstr = instr;
588 : uint8_t ucRegNum;
589 :
590 72 : switch (TRACE_HIBIT2_OPCODE(opcode)) {
591 : /* 定位PC位置 */
592 18 : case DW_CFA_ADVANCE_LOC:
593 18 : pstFrameRInfo->pc += TRACE_LOBIT6_OPCODE((uintptr_t)opcode) * pstFrameRInfo->codeAlign;
594 18 : SCD_DLOG_INF(
595 : "DW_CFA_ADVANCE_LOC %lu to %lx", TRACE_LOBIT6_OPCODE((uintptr_t)opcode) * pstFrameRInfo->codeAlign,
596 : pstFrameRInfo->pc);
597 18 : break;
598 : /* 依据CFA偏移量获取寄存器的值 */
599 18 : case DW_CFA_OFFSET:
600 18 : ucRegNum = (uint8_t)TRACE_LOBIT6_OPCODE(opcode);
601 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
602 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
603 18 : offset = (intptr_t)offsetTemp * pstFrameRInfo->dataAlign;
604 18 : pstFrameRInfo->frameStateInfo.regInfo[ucRegNum & REG_VAILD_MASK].regHow = REG_SAVED_OFFSET;
605 18 : pstFrameRInfo->frameStateInfo.regInfo[ucRegNum & REG_VAILD_MASK].regLoc.offset = offset;
606 18 : SCD_DLOG_INF("DW_CFA_OFFSET reg %hhu at %ld", ucRegNum, offsetTemp);
607 18 : break;
608 : /* 指定寄存器信息不保存 */
609 18 : case DW_CFA_RESTORE:
610 18 : ucRegNum = (uint8_t)TRACE_LOBIT6_OPCODE(opcode);
611 18 : pstFrameRInfo->frameStateInfo.regInfo[ucRegNum & REG_VAILD_MASK].regHow = REG_UNSAVED;
612 18 : SCD_DLOG_INF("DW_CFA_RESTORE reg %hhu ", ucRegNum);
613 18 : break;
614 18 : default:
615 18 : tmpInstr = NULL;
616 18 : break;
617 : }
618 :
619 72 : return tmpInstr;
620 : }
621 :
622 : /**
623 : * @brief 解析PC位置信息
624 : *
625 : * @param [in] opcode 操作类型
626 : * @param [in] instr 指令地址
627 : * @param [out] pstFrameRInfo 推栈状态信息结构体
628 : *
629 : * @return 指令地址
630 : */
631 108 : STATIC const uint8_t* TraceUnwindPCLocParse(
632 : ScdDwarf* dwarf, uint8_t opcode, const uint8_t* instr, TraceFrameRegStateInfo* pstFrameRInfo)
633 : {
634 : uintptr_t pc;
635 108 : const uint8_t* tmpInstr = instr;
636 :
637 108 : switch (opcode) {
638 : /* 直接设置PC指针的位置 */
639 36 : case DW_CFA_SET_LOC:
640 36 : tmpInstr = TraceReadEncodeValue(dwarf, pstFrameRInfo->fdeEnc, tmpInstr, &pc);
641 36 : if (tmpInstr == NULL) {
642 18 : return NULL;
643 : }
644 18 : pstFrameRInfo->pc = pc;
645 18 : SCD_DLOG_INF("DW_CFA_SET_LOC %lx", pc);
646 18 : break;
647 18 : case DW_CFA_ADVANCE_LOC1:
648 18 : pstFrameRInfo->pc += *tmpInstr * pstFrameRInfo->codeAlign;
649 18 : SCD_DLOG_INF("DW_CFA_ADVANCE_LOC1 %lu to %lx", *tmpInstr * pstFrameRInfo->codeAlign, pstFrameRInfo->pc);
650 18 : tmpInstr += sizeof(uint8_t);
651 18 : break;
652 18 : case DW_CFA_ADVANCE_LOC2:
653 18 : pstFrameRInfo->pc += TraceReadU16(tmpInstr, sizeof(uint16_t)) * pstFrameRInfo->codeAlign;
654 18 : tmpInstr += sizeof(uint16_t);
655 18 : break;
656 18 : case DW_CFA_ADVANCE_LOC4:
657 18 : pstFrameRInfo->pc += TraceReadU32(tmpInstr, sizeof(uint32_t)) * pstFrameRInfo->codeAlign;
658 18 : tmpInstr += sizeof(uint32_t);
659 18 : break;
660 18 : default:
661 18 : tmpInstr = NULL;
662 18 : break;
663 : }
664 :
665 90 : return tmpInstr;
666 : }
667 :
668 : /**
669 : * @brief 解析CFA信息
670 : *
671 : * @param [in] opcode 操作类型
672 : * @param [in] instr 指令地址
673 : * @param [out] pstFrameRInfo 推栈状态信息结构体
674 : *
675 : * @return 指令地址
676 : */
677 126 : STATIC const uint8_t* TraceUnwindCFADefParse(
678 : ScdDwarf* dwarf, uint8_t opcode, const uint8_t* instr, TraceFrameRegStateInfo* pstFrameRInfo)
679 : {
680 : uintptr_t regTmp;
681 : uintptr_t offsetTemp;
682 : intptr_t offset;
683 126 : const uint8_t* tmpInstr = instr;
684 :
685 126 : switch (opcode) {
686 : /* 获取CFA所需的寄存器和偏移 */
687 18 : case DW_CFA_DEF_CFA:
688 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
689 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
690 18 : pstFrameRInfo->frameStateInfo.cfaReg = regTmp;
691 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
692 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
693 18 : pstFrameRInfo->frameStateInfo.cfaOffset = (intptr_t)offsetTemp;
694 18 : pstFrameRInfo->frameStateInfo.cfaHow = VOS_CFA_REG_OFFSET;
695 18 : SCD_DLOG_INF("DW_CFA_DEF_CFA %lu %lu", regTmp, offsetTemp);
696 18 : break;
697 : /* DWARF3指令,操作数是负数 */
698 18 : case DW_CFA_DEF_CFA_SF:
699 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
700 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
701 18 : pstFrameRInfo->frameStateInfo.cfaReg = regTmp;
702 18 : tmpInstr = TraceReadLeb128(dwarf, tmpInstr, &offset);
703 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read leb128 failed");
704 18 : offset = (intptr_t)(offset * pstFrameRInfo->dataAlign);
705 18 : pstFrameRInfo->frameStateInfo.cfaOffset = offset;
706 18 : pstFrameRInfo->frameStateInfo.cfaHow = VOS_CFA_REG_OFFSET;
707 18 : SCD_DLOG_INF("DW_CFA_DEF_CFA_SF %lu %ld", regTmp, offset);
708 18 : break;
709 : /* 获取CFA所需的寄存器 */
710 18 : case DW_CFA_DEF_CFA_REGISTER:
711 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
712 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
713 18 : pstFrameRInfo->frameStateInfo.cfaReg = regTmp;
714 18 : pstFrameRInfo->frameStateInfo.cfaHow = VOS_CFA_REG_OFFSET;
715 18 : SCD_DLOG_INF("DW_CFA_DEF_CFA_REGISTER %lu", regTmp);
716 18 : break;
717 : /* 获取CFA所需的偏移 */
718 18 : case DW_CFA_DEF_CFA_OFFSET:
719 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
720 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
721 18 : pstFrameRInfo->frameStateInfo.cfaOffset = (intptr_t)offsetTemp;
722 18 : SCD_DLOG_INF("DW_CFA_DEF_CFA_OFFSET %lu", offsetTemp);
723 18 : break;
724 18 : case DW_CFA_DEF_CFA_OFFSET_SF:
725 18 : tmpInstr = TraceReadLeb128(dwarf, tmpInstr, &offset);
726 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read leb128 failed");
727 18 : offset = (intptr_t)(offset * pstFrameRInfo->dataAlign);
728 18 : pstFrameRInfo->frameStateInfo.cfaOffset = offset;
729 18 : SCD_DLOG_INF("DW_CFA_DEF_CFA_OFFSET_SF %ld", offset);
730 18 : break;
731 : /* 通过DW_OP 指令获取CFA */
732 18 : case DW_CFA_DEF_CFA_EXPRESSION:
733 18 : pstFrameRInfo->frameStateInfo.cfaExp = tmpInstr;
734 18 : pstFrameRInfo->frameStateInfo.cfaHow = VOS_CFA_EXP;
735 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
736 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
737 18 : tmpInstr += offsetTemp;
738 18 : SCD_DLOG_INF("DW_CFA_DEF_CFA_EXPRESSION %lu", offsetTemp);
739 18 : break;
740 18 : default:
741 18 : tmpInstr = NULL;
742 18 : break;
743 : }
744 :
745 126 : return tmpInstr;
746 : }
747 :
748 : /**
749 : * @brief 解析寄存器定义信息
750 : *
751 : * @param [in] opcode 操作类型
752 : * @param [in] instr 指令地址
753 : * @param [out] pstFrameRInfo 推栈状态信息结构体
754 : *
755 : * @return 指令地址
756 : */
757 90 : STATIC const uint8_t* TraceUnwindRegValueDefParse(
758 : ScdDwarf* dwarf, uint8_t opcode, const uint8_t* instr, TraceFrameRegStateInfo* pstFrameRInfo)
759 : {
760 : uintptr_t regTmp;
761 : uintptr_t offsetTemp;
762 : intptr_t offset;
763 90 : const uint8_t* tmpInstr = instr;
764 90 : TraceStagRegInfo* pstRegInfo = NULL;
765 90 : switch (opcode) {
766 : /* 依据CFA的值获取寄存器信息 */
767 36 : case DW_CFA_VAL_OFFSET:
768 36 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
769 36 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
770 36 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
771 36 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
772 36 : offset = (intptr_t)offsetTemp * pstFrameRInfo->dataAlign;
773 36 : pstRegInfo = &(pstFrameRInfo->frameStateInfo.regInfo[regTmp & REG_VAILD_MASK]);
774 36 : pstRegInfo->regHow = REG_SAVED_VAL_OFFSET;
775 36 : pstRegInfo->regLoc.offset = offset;
776 36 : SCD_DLOG_INF("DW_CFA_VAL_OFFSET");
777 36 : break;
778 18 : case DW_CFA_VAL_OFFSET_SF:
779 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
780 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
781 18 : tmpInstr = TraceReadLeb128(dwarf, tmpInstr, &offset);
782 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read leb128 failed");
783 18 : offset = (intptr_t)(offset * pstFrameRInfo->dataAlign);
784 18 : pstRegInfo = &(pstFrameRInfo->frameStateInfo.regInfo[regTmp & REG_VAILD_MASK]);
785 18 : pstRegInfo->regHow = REG_SAVED_VAL_OFFSET;
786 18 : pstRegInfo->regLoc.offset = offset;
787 18 : SCD_DLOG_INF("DW_CFA_VAL_OFFSET_SF");
788 18 : break;
789 18 : case DW_CFA_VAL_EXPRESSION:
790 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
791 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
792 18 : pstRegInfo = &(pstFrameRInfo->frameStateInfo.regInfo[regTmp & REG_VAILD_MASK]);
793 18 : pstRegInfo->regHow = REG_SAVED_VAL_EXP;
794 18 : pstRegInfo->regLoc.valExp = tmpInstr;
795 :
796 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
797 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
798 18 : tmpInstr += offsetTemp;
799 18 : SCD_DLOG_INF("DW_CFA_VAL_EXPRESSION");
800 18 : break;
801 18 : default:
802 18 : tmpInstr = NULL;
803 18 : break;
804 : }
805 :
806 90 : return tmpInstr;
807 : }
808 :
809 : /**
810 : * @brief 解析其他类型的操作码
811 : *
812 : * @param [in] opcode 操作类型
813 : * @param [in] instr 指令地址
814 : * @param [in] pstStoreFrameRegState 上一轮推栈状态信息结构体
815 : * @param [out] pstFrameRInfo 推栈状态信息结构体
816 : *
817 : * @return 指令地址
818 : */
819 126 : STATIC const uint8_t* TraceUnwindOtherCodeParse(
820 : ScdDwarf* dwarf, uint8_t opcode, const uint8_t* instr, TraceFrameStateInfo* pstStoreFrameRegState,
821 : TraceFrameRegStateInfo* pstFrameRInfo)
822 : {
823 126 : uintptr_t offsetTemp = 0;
824 126 : TraceStagRegInfo* pstRegInfo = NULL;
825 126 : const uint8_t* tmpInstr = instr;
826 :
827 126 : switch (opcode) {
828 36 : case DW_CFA_NOP:
829 36 : SCD_DLOG_INF("DW_CFA_NOP");
830 36 : break;
831 : /* 将寄存器组的设置状态放在链表前与DW_CFA_RES_STATE配对 */
832 18 : case DW_CFA_REMEMBER_STATE:
833 18 : (void)memcpy_s(
834 18 : (void*)pstStoreFrameRegState, sizeof(TraceFrameStateInfo), (void*)&pstFrameRInfo->frameStateInfo,
835 : sizeof(TraceFrameStateInfo));
836 18 : SCD_DLOG_INF("DW_CFA_REMEMBER_STATE");
837 18 : break;
838 : /* 将链表中最前面的寄存器组设置信息取出,与DW_CFA_REM_STATE配对使用 */
839 18 : case DW_CFA_RESTORE_STATE:
840 18 : (void)memcpy_s(
841 18 : (void*)&pstFrameRInfo->frameStateInfo, sizeof(TraceFrameStateInfo), (void*)pstStoreFrameRegState,
842 : sizeof(TraceFrameStateInfo));
843 18 : SCD_DLOG_INF("DW_CFA_RESTORE_STATE");
844 18 : break;
845 : /*
846 : * 该指令只用于sun系列的SPARC架构,i686不涉及
847 : * 从16号寄存器到31号寄存器号寄存器偏移值计算方法
848 : * 16 不是魔鬼数字 表示16号寄存器
849 : */
850 18 : case DW_CFA_GNU_WIN_SAVE:
851 306 : for (uint32_t idx = 16U; idx < VOS_CORE_REGS_NUM; idx++) { /* 16代表寄存器 */
852 288 : pstRegInfo = &(pstFrameRInfo->frameStateInfo.regInfo[idx & REG_VAILD_MASK]);
853 288 : pstRegInfo->regHow = REG_SAVED_OFFSET;
854 288 : pstRegInfo->regLoc.offset = ((intptr_t)idx - 16LL) * (intptr_t)sizeof(void*); /* 16代表寄存器 */
855 : }
856 18 : SCD_DLOG_INF("DW_CFA_GNU_WIN_SAVE");
857 18 : break;
858 : /* 当CPU为cr16c时,才有该unwind指令,i686没有该指令 */
859 18 : case DW_CFA_GNU_ARG_SIZE:
860 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, &offsetTemp);
861 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
862 18 : SCD_DLOG_INF("DW_CFA_GNU_ARG_SIZE");
863 18 : break;
864 18 : default:
865 18 : tmpInstr = NULL;
866 18 : break;
867 : }
868 :
869 126 : return tmpInstr;
870 : }
871 :
872 : /**
873 : * @brief 解析关于寄存器的unwind操作码
874 : *
875 : * @param [in] opcode 操作类型
876 : * @param [in] instr 指令地址
877 : * @param [out] pstInfo 推栈状态信息结构体
878 : *
879 : * @return 指令地址
880 : */
881 4572 : STATIC const uint8_t* TraceUnwindRegDefParse(
882 : ScdDwarf* dwarf, uint8_t opcode, const uint8_t* instr, TraceFrameRegStateInfo* pstInfo)
883 : {
884 : intptr_t offset;
885 : uintptr_t regTmp;
886 4572 : TraceStagRegInfo* pstRegInfo = NULL;
887 4572 : const uint8_t* tmpInstr = instr;
888 :
889 4572 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
890 4572 : pstRegInfo = &(pstInfo->frameStateInfo.regInfo[regTmp & REG_VAILD_MASK]);
891 :
892 4572 : switch (opcode) {
893 : /* 扩展类型: 依据CFA偏移量获取寄存器 */
894 18 : case DW_CFA_OFFSET_EXTENDED:
895 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
896 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
897 18 : offset = (intptr_t)regTmp * pstInfo->dataAlign;
898 18 : pstRegInfo->regHow = REG_SAVED_OFFSET;
899 18 : pstRegInfo->regLoc.offset = offset;
900 18 : SCD_DLOG_INF("reg[%lu] DW_CFA_OFFSET_EXTENDED %lx", regTmp & REG_VAILD_MASK, regTmp);
901 18 : break;
902 : /* dwarf3 新增的unwind指令,操作数有有符号leb128类型 */
903 18 : case DW_CFA_OFF_EXTENDED_SF:
904 18 : tmpInstr = TraceReadLeb128(dwarf, tmpInstr, &offset);
905 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read leb128 failed");
906 18 : offset = (intptr_t)(offset * pstInfo->dataAlign);
907 18 : pstRegInfo->regHow = REG_SAVED_OFFSET;
908 18 : pstRegInfo->regLoc.offset = offset;
909 18 : SCD_DLOG_INF("reg[%lu] DW_CFA_OFFSET_EXT_SF %lx", regTmp & REG_VAILD_MASK, offset);
910 18 : break;
911 : /* 该条指令被DW_CFA_OFF_EXT_SF指令替换, 但是在老的PowerPC编码里会有 */
912 18 : case DW_CFA_GNU_NEG_OFF_EXT:
913 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
914 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
915 18 : regTmp = (uintptr_t)(regTmp * (uintptr_t)pstInfo->dataAlign);
916 18 : pstRegInfo->regHow = REG_SAVED_OFFSET;
917 18 : pstRegInfo->regLoc.offset = -(intptr_t)regTmp;
918 18 : SCD_DLOG_INF("reg[%lu] DW_CFA_GNU_NEG_OFF_EXT: %lx", regTmp & REG_VAILD_MASK, regTmp);
919 18 : break;
920 36 : case DW_CFA_SAME_VALUE:
921 : case DW_CFA_RESTORE_EXTENDED:
922 36 : pstRegInfo->regHow = REG_UNSAVED;
923 36 : SCD_DLOG_INF("reg[%lu] DW_CFA_RESTORE_EXTENDED", regTmp & REG_VAILD_MASK);
924 36 : break;
925 18 : case DW_CFA_UNDEFINED:
926 18 : pstRegInfo->regHow = REG_UNDEFINED;
927 18 : SCD_DLOG_INF("reg[%lu] DW_CFA_UNDEFINED", regTmp & REG_VAILD_MASK);
928 18 : break;
929 : /* 寄存器号变化 */
930 18 : case DW_CFA_REGISTER:
931 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
932 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
933 18 : pstRegInfo->regHow = REG_SAVED_REG;
934 18 : pstRegInfo->regLoc.reg = regTmp;
935 18 : SCD_DLOG_INF("reg[%lu] DW_CFA_REGISTER: %lx", regTmp & REG_VAILD_MASK, regTmp);
936 18 : break;
937 : /* 通过DW_OP 指令获取寄存器 */
938 18 : case DW_CFA_EXPRESSION:
939 18 : pstRegInfo->regHow = REG_SAVED_EXP;
940 18 : pstRegInfo->regLoc.valExp = tmpInstr;
941 18 : tmpInstr = TraceReadUleb128(dwarf, tmpInstr, ®Tmp);
942 18 : SCD_CHK_EXPR_ACTION(tmpInstr == NULL, return NULL, "read uleb128 failed");
943 18 : tmpInstr = tmpInstr + regTmp;
944 18 : SCD_DLOG_INF("reg[%lu] DW_CFA_EXPRESSION: %lx", regTmp & REG_VAILD_MASK, regTmp);
945 18 : break;
946 4428 : default:
947 4428 : tmpInstr = NULL;
948 4428 : break;
949 : }
950 :
951 4572 : return tmpInstr;
952 : }
953 :
954 : /**
955 : * @brief 解析unwind表达式和DW_OP指令
956 : *
957 : * @param [in] opStart DW_OP指令的起始地址
958 : * @param [in] opEnd DW_OP指令的结束地址
959 : * @param [in] coreRegs 寄存器信息
960 : * @param [out] result 执行dw_op指令之后的返回值
961 : * @param [in] initial 放入栈底的初始值
962 : * @param [in] args 栈限制地址
963 : *
964 : * @return 指令地址
965 : */
966 4626 : TraStatus TraceStackOpExc(
967 : ScdDwarf* dwarf, const uint8_t* opStart, const uint8_t* opEnd, const ScdRegs* coreRegs, uintptr_t* ptrResult,
968 : uintptr_t initial, const ScdDwarfStepArgs* args)
969 : {
970 4626 : uintptr_t stackContent[VOS_OP_STACK_DEPTH] = {0};
971 4626 : uint32_t idx = 0;
972 4626 : uint8_t opType = 0;
973 4626 : uintptr_t result = 0;
974 : intptr_t offset;
975 : TraStatus ret;
976 4626 : const uint8_t* pStartTmp = opStart;
977 4626 : stackContent[idx & VOS_OP_STACK_MASK] = initial;
978 4626 : idx++;
979 :
980 : /* 执行unwind指令中类型为DWARF expresion的指令,该指令是一串DW_OP类型指令,该指令
981 : * 操作可看成栈操作,用数组表示一个栈,每次执行完,取栈顶的数据返回
982 : * 分为以下几种类型 */
983 7506 : while (pStartTmp < opEnd) {
984 5040 : if (pStartTmp == NULL) {
985 18 : return TRACE_FAILURE;
986 : }
987 5022 : opType = *pStartTmp;
988 5022 : pStartTmp++;
989 :
990 : /* 数值,从0到31,用于后续逻辑处理 */
991 5022 : if (VOS_ENC_OP_LIT(opType)) {
992 576 : result = (uintptr_t)opType - (uintptr_t)DW_OP_LIT0;
993 4446 : } else if (VOS_ENC_OP_REG(opType)) { /* 无操作数,类型表示寄存器号 */
994 576 : result = coreRegs->r[(opType - DW_OP_REG0) & REG_VAILD_MASK];
995 3870 : } else if (VOS_ENC_OP_BREG(opType)) { /* 一个操作数,保存有符号leb128的偏移 */
996 576 : pStartTmp = TraceReadLeb128(dwarf, pStartTmp, &offset);
997 576 : SCD_CHK_EXPR_ACTION(pStartTmp == NULL, return TRACE_FAILURE, "read leb128 failed");
998 576 : result = coreRegs->r[(opType - DW_OP_BREG0) & REG_VAILD_MASK] + (uintptr_t)offset;
999 3294 : } else if (VOS_ENC_OP_CONST(opType)) { /* 读取该编码类型的一个数据 */
1000 180 : pStartTmp = TraceOpConstNumGet(dwarf, opType, pStartTmp, &result);
1001 180 : if (pStartTmp == NULL) {
1002 0 : return TRACE_FAILURE;
1003 : }
1004 3114 : } else if (VOS_ENC_OP_STACK_OPR(opType)) { /* 在栈中处理数据 */
1005 630 : pStartTmp = TraceOpStackDataOpt(opType, stackContent, &idx, pStartTmp, &result);
1006 630 : if (pStartTmp == NULL) {
1007 90 : return TRACE_FAILURE;
1008 : }
1009 2484 : } else if (VOS_ENC_OP_ONE_DATA(opType)) { /* 栈中一个数的操作流程 */
1010 0 : pStartTmp = TraceOpStackOneDataOpt(dwarf, opType, stackContent, &idx, pStartTmp, args, &result);
1011 0 : if (pStartTmp == NULL) {
1012 0 : return TRACE_FAILURE;
1013 : }
1014 2484 : } else if (VOS_ENC_OP_TWO_DATA(opType)) { /* 栈中两个数的操作流程 */
1015 306 : ret = TraceOpStackTwoDataOpt(opType, stackContent, &idx, &result);
1016 306 : if (ret != TRACE_SUCCESS) {
1017 0 : return ret;
1018 : }
1019 2178 : } else if (VOS_ENC_OP_OTHER_OPR(opType)) {
1020 126 : pStartTmp = TraceOpStackOtherOpt(dwarf, opType, stackContent, &idx, pStartTmp, coreRegs, &result);
1021 : } else {
1022 2052 : return TRACE_FAILURE;
1023 : }
1024 :
1025 : /* 排除非压栈指令 */
1026 2880 : if ((idx < VOS_OP_STACK_DEPTH) && (!(VOS_IS_NO_PUSH_CODE(opType)))) {
1027 2700 : stackContent[idx & VOS_OP_STACK_MASK] = result;
1028 2700 : idx++;
1029 180 : } else if (idx >= VOS_OP_STACK_DEPTH) {
1030 0 : return TRACE_FAILURE;
1031 : } else {
1032 : ;
1033 : }
1034 : }
1035 :
1036 2466 : if (idx < 1) {
1037 36 : return TRACE_FAILURE;
1038 : }
1039 2430 : idx--;
1040 : /* 取出栈顶数据 */
1041 2430 : *ptrResult = stackContent[idx & VOS_OP_STACK_MASK];
1042 :
1043 2430 : return TRACE_SUCCESS;
1044 : }
1045 :
1046 : /**
1047 : * @brief 解析unwind指令
1048 : * @param [in] addrRange 要解析的指令地址范围
1049 : * @param [out] frameRegState 推栈状态信息结构体
1050 : * @param [in] isFEDTable 是FDE还是CIE
1051 : *
1052 : * @return : !=0 failure; ==0 success
1053 : */
1054 72 : TraStatus TraceUnwindParseFn(
1055 : ScdDwarf* dwarf, TraceAddrRange* addrRange, TraceFrameRegStateInfo* frameRegState, bool isFEDTable)
1056 : {
1057 72 : const uint8_t* instr = (uint8_t*)addrRange->start;
1058 : uint8_t ucCurInsn;
1059 : uint8_t ucLowCurIns;
1060 72 : if (instr == NULL) {
1061 0 : SCD_DLOG_ERR("invalid addr start");
1062 0 : return TRACE_FAILURE;
1063 : }
1064 72 : TraceFrameStateInfo stStoreFrameRegState = {0};
1065 108 : while (instr < (uint8_t*)addrRange->end) {
1066 : // 当pc值等于ret时,需要再推一层
1067 90 : if (isFEDTable && frameRegState->pc > frameRegState->ret) {
1068 0 : return TRACE_SUCCESS;
1069 : }
1070 90 : ucCurInsn = *instr;
1071 90 : instr++;
1072 :
1073 : /* 操作码高两位非0时,低6位可表征寄存器号 */
1074 90 : if (TRACE_HIBIT2_OPCODE(ucCurInsn) != 0) {
1075 18 : instr = TraceUnwindOpcodeParse(dwarf, ucCurInsn, instr, frameRegState);
1076 18 : if (instr == NULL) {
1077 18 : SCD_DLOG_ERR("invalid instr");
1078 18 : return TRACE_FAILURE;
1079 : }
1080 0 : continue;
1081 : }
1082 :
1083 : /* 高2位为0时,低六位就是指令unwind类型 */
1084 72 : ucLowCurIns = (uint8_t)TRACE_LOBIT6_OPCODE(ucCurInsn);
1085 : /* 直接设置PC指针的位置 */
1086 72 : if (VOS_INS_PC_LOC(ucLowCurIns)) {
1087 0 : instr = TraceUnwindPCLocParse(dwarf, ucLowCurIns, instr, frameRegState);
1088 72 : } else if (VOS_INS_REG_DEF(ucLowCurIns)) { /* 获取寄存器的计算状态 */
1089 0 : instr = TraceUnwindRegDefParse(dwarf, ucLowCurIns, instr, frameRegState);
1090 72 : } else if (VOS_INS_CFA_DEF(ucLowCurIns)) { /* 获取CFA的计算状态 */
1091 0 : instr = TraceUnwindCFADefParse(dwarf, ucLowCurIns, instr, frameRegState);
1092 72 : } else if (VOS_INS_REG_VALUE_DEF(ucLowCurIns)) { /* 获取寄存器值的计算状态 */
1093 18 : instr = TraceUnwindRegValueDefParse(dwarf, ucLowCurIns, instr, frameRegState);
1094 54 : } else if (VOS_INS_OTHER_DEF(ucLowCurIns)) { /* 其他unwind指令解析过程 */
1095 18 : instr = TraceUnwindOtherCodeParse(dwarf, ucLowCurIns, instr, &stStoreFrameRegState, frameRegState);
1096 : } else {
1097 36 : SCD_DLOG_ERR("invalid opcode");
1098 36 : return TRACE_FAILURE;
1099 : }
1100 36 : if (instr == NULL) {
1101 0 : SCD_DLOG_ERR("invalid instr");
1102 0 : return TRACE_FAILURE;
1103 : }
1104 : }
1105 18 : return TRACE_SUCCESS;
1106 : }
|