LCOV - code coverage report
Current view: top level - atrace/utrace/stacktrace - stacktrace_unwind_instr.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.2 % 642 624
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 18 18

            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, &regData);
      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, &regData);
      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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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, &regTmp);
     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              : }
        

Generated by: LCOV version 2.0-1