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