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

Generated by: LCOV version 2.0-1