LCOV - code coverage report
Current view: top level - adump/exception - dump_args_callback.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.7 % 137 127
Test Date: 2026-07-28 10:54:24 Functions: 100.0 % 9 9

            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 "dump_args_callback.h"
      12              : #include "dfx_args_parser.h"
      13              : #include "dump_memory.h"
      14              : #include "exception_info_common.h"
      15              : #include "kernel_symbol_locator.h"
      16              : #include "str_utils.h"
      17              : #include "log/adx_log.h"
      18              : #include "log/hdc_log.h"
      19              : 
      20              : namespace Adx {
      21              : 
      22           25 : DumpArgsCallback::DumpArgsCallback(const rtExceptionInfo &exception, const ExceptionDumpInfo &info,
      23           25 :                                      const std::string &dumpPath)
      24           25 :     : exception_(exception),
      25           25 :       info_(info),
      26           25 :       dumpPath_(dumpPath),
      27           75 :       dumpFilePath_(dumpPath + "/" +
      28          100 :         std::string(info.kernelDisplayName[0] != '\0' ? info.kernelDisplayName : "exception_info") + "." +
      29          100 :         std::to_string(exception.streamid) + "." + std::to_string(exception.taskid) + "." +
      30          100 :         std::to_string(info.coreType) + "." + std::to_string(info.coreId) + "." +
      31           50 :         SysUtils::GetCurrentTimeWithMillisecond()),
      32           50 :       dumpFile_(exception.deviceid, dumpFilePath_)
      33              : {
      34           25 : }
      35              : 
      36            4 : int32_t DumpArgsCallback::DumpKernelBin()
      37              : {
      38            4 :     std::string kernelName(info_.kernelName);
      39            4 :     if (info_.bin == nullptr || kernelName.empty()) {
      40            3 :         return ADUMP_SUCCESS;
      41              :     }
      42            1 :     IDE_LOGI("Dump kernel bin file. bin=%p, kernelName=%s", info_.bin, kernelName.c_str());
      43            1 :     KernelInfoCollector collector;
      44            1 :     int32_t ret = collector.InitFromBinHandle(info_.bin, kernelName);
      45            1 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      46              :         "Init for dump kernel bin failed. ret=%d, bin=%p, kernelName=%s.", ret, info_.bin, kernelName.c_str());
      47              : 
      48            1 :     ret = collector.StartCollectKernel(dumpPath_);
      49            1 :     IDE_CTRL_VALUE_WARN(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      50              :         "StartCollectKernel failed, kernelName=%s.", kernelName.c_str());
      51              : 
      52            1 :     IDE_LOGI("DumpKernelBin success, kernelName=%s.", kernelName.c_str());
      53            1 :     return ADUMP_SUCCESS;
      54            4 : }
      55              : 
      56            6 : int32_t DumpArgsCallback::DumpKernelErrorSymbols()
      57              : {
      58            6 :     if (info_.bin == nullptr) {
      59            2 :         return ADUMP_SUCCESS;
      60              :     }
      61            4 :     KernelSymbolLocator locator;
      62            4 :     int32_t ret = locator.InitFromBinHandle(info_.bin);
      63            4 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      64              :         "KernelSymbolLocator InitFromBinHandle failed for callback exception. ret=%d", ret);
      65            3 :     locator.UpdateStartPCFromDeviceAddr(info_.bin);
      66              : 
      67            3 :     ExceptionRegInfo exceptionRegInfo{0, nullptr};
      68            3 :     ret = ExceptionInfoCommon::GetExceptionRegInfo(exception_, exceptionRegInfo);
      69            3 :     IDE_CTRL_VALUE_WARN(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      70              :         "Get exception register information failed for callback exception. ret=%d", ret);
      71              : 
      72            2 :     ret = locator.LocateAndPrintErrorSymbolsForCore(info_.coreId, info_.coreType, exceptionRegInfo);
      73            2 :     IDE_CTRL_VALUE_WARN(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      74              :         "LocateAndPrintErrorSymbolsForCore failed for callback exception. ret=%d, coreId=%u, coreType=%u.",
      75              :             ret, info_.coreId, info_.coreType);
      76              : 
      77            1 :     return ADUMP_SUCCESS;
      78            4 : }
      79              : 
      80            3 : int32_t DumpArgsCallback::QueryDfxIsTikInfo(rtFuncHandle funcHandle)
      81              : {
      82            3 :     size_t isTikSize = 0;
      83            3 :     rtError_t rtRet = rtFunctionGetMetaInfoSize(funcHandle, RT_FUNCTION_TYPE_L0_EXCEPTION_DFX_IS_TIK, &isTikSize);
      84            3 :     if (rtRet != RT_ERROR_NONE || isTikSize == 0 || isTikSize < sizeof(uint32_t)) {
      85            1 :         IDE_LOGW("rtFunctionGetMetaInfoSize for dfxIsTik failed, will set dfxIsTik with false. "
      86              :             "rtRet=%d, kernelName=%s", rtRet, info_.kernelName);
      87            1 :         return ADUMP_FAILED;
      88              :     }
      89              : 
      90            2 :     std::vector<uint8_t> isTikBuffer(isTikSize);
      91            2 :     rtRet = rtFunctionGetMetaInfo(funcHandle, RT_FUNCTION_TYPE_L0_EXCEPTION_DFX_IS_TIK, 
      92            2 :         isTikBuffer.data(), isTikSize);
      93            2 :     if (rtRet != RT_ERROR_NONE) {
      94            1 :         IDE_LOGW("rtFunctionGetMetaInfo for isTik failed, will set dfxIsTik with false. "
      95              :             "ret=%d, kernelName=%s, isTikSize=%zu.",  rtRet, info_.kernelName, isTikSize);
      96            1 :         return ADUMP_FAILED;
      97              :     }
      98              : 
      99            1 :     uint32_t isTik = 0;
     100            1 :     isTik = *reinterpret_cast<uint32_t*>(isTikBuffer.data());
     101            1 :     isTik_ = (isTik == 1U) ? true : false;
     102            1 :     IDE_LOGI("Query dfxIsTik info success. kernelName=%s, dfxIsTik=%u", info_.kernelName, isTik);
     103            1 :     return ADUMP_SUCCESS;
     104            2 : }
     105              : 
     106            7 : int32_t DumpArgsCallback::QueryDfxInfo(std::vector<uint8_t> &dfxBuffer)
     107              : {
     108            7 :     rtFuncHandle funcHandle = nullptr;
     109            7 :     rtError_t rtRet = rtBinaryGetFunctionByName(info_.bin, info_.kernelName, &funcHandle);
     110            7 :     IDE_CTRL_VALUE_FAILED(rtRet == RT_ERROR_NONE && funcHandle != nullptr, return ADUMP_FAILED,
     111              :         "rtBinaryGetFunctionByName failed, ret=%d, bin=%p, kernelName=%s.", rtRet, info_.bin, info_.kernelName);
     112              : 
     113            6 :     size_t dfxSize = 0;
     114            6 :     rtRet = rtFunctionGetMetaInfoSize(funcHandle, RT_FUNCTION_TYPE_DFX_TYPE, &dfxSize);
     115            6 :     IDE_CTRL_VALUE_FAILED(rtRet == RT_ERROR_NONE && dfxSize > 0, return ADUMP_FAILED,
     116              :         "rtFunctionGetMetaInfoSize failed, ret=%d, kernelName=%s, dfxSize=%zu.", rtRet, info_.kernelName, dfxSize);
     117            5 :     IDE_CTRL_VALUE_FAILED(dfxSize <= UINT16_MAX, return ADUMP_FAILED,
     118              :         "Dfx size exceeds uint16_t max, dfxSize=%zu", dfxSize);
     119              :     
     120            4 :     dfxBuffer.resize(dfxSize);
     121            4 :     rtRet = rtFunctionGetMetaInfo(funcHandle, RT_FUNCTION_TYPE_DFX_TYPE, dfxBuffer.data(), dfxSize);
     122            4 :     IDE_CTRL_VALUE_FAILED(rtRet == RT_ERROR_NONE, return ADUMP_FAILED,
     123              :         "rtFunctionGetMetaInfo failed, ret=%d, kernelName=%s, dfxSize=%zu.", rtRet, info_.kernelName, dfxSize);
     124              : 
     125            3 :     (void)QueryDfxIsTikInfo(funcHandle);
     126              : 
     127            3 :     IDE_LOGI("Query kernel dfx args info success. kernelName=%s, dfxSize=%zu, isTik=%d", 
     128              :         info_.kernelName, dfxSize, isTik_);
     129            3 :     return ADUMP_SUCCESS;
     130              : }
     131              : 
     132            9 : int32_t DumpArgsCallback::DumpDfxArgs()
     133              : {
     134            9 :     if (info_.argAddr == nullptr || info_.argSize == 0 || info_.bin == nullptr || info_.kernelName[0] == '\0') {
     135            2 :         return ADUMP_SUCCESS;
     136              :     }
     137              : 
     138            7 :     IDE_LOGI("Begin to dump dfx args tensors. argAddr=%p, argSize=%u, bin=%p, kernelName=%s",
     139              :              info_.argAddr, info_.argSize, info_.bin, info_.kernelName);
     140              : 
     141            7 :     int32_t ret = QueryDfxInfo(dfxBuffer_);
     142            7 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED, "Query kernel dfx info failed.");
     143              : 
     144            3 :     DfxArgsParser parser;
     145            3 :     ret = parser.Init(info_.argAddr, info_.argSize, dfxBuffer_.data(), static_cast<uint16_t>(dfxBuffer_.size()));
     146            3 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED, "Dfx args parser init failed.");
     147              :     
     148            3 :     parser.SetIsTik(isTik_);
     149            3 :     ret = parser.InitTensorModeInfo();
     150            3 :     IDE_CHECK_RET(ret, return ADUMP_FAILED);
     151              :     
     152            0 :     ret = parser.ParseAll();
     153            0 :     IDE_CHECK_RET(ret, return ADUMP_FAILED);
     154              :     
     155            0 :     tensorBuffer_ = parser.GetTensors();
     156            0 :     workspaces_ = parser.GetWorkspaces();
     157            0 :     logRecord_ = parser.GetLogRecords();
     158              :     
     159            0 :     IDE_LOGI("Dfx args tensors are parsed finished. tensor size=%zu, workspace size=%zu.",
     160              :         tensorBuffer_.size(), workspaces_.size());
     161              :     
     162            0 :     dumpFile_.SetTensorBuffer(tensorBuffer_);
     163            0 :     dumpFile_.SetWorkspaces(workspaces_);
     164              :     
     165            0 :     IDE_LOGI("End to dump dfx args tensors.");
     166            0 :     return ADUMP_SUCCESS;
     167            3 : }
     168              : 
     169            6 : int32_t DumpArgsCallback::DumpExtraTensors()
     170              : {
     171            6 :     if (info_.extraTensorNum == 0) {
     172            2 :         return ADUMP_SUCCESS;
     173              :     }
     174            4 :     if (info_.extraTensorNum > EXCEPTION_DUMP_MAX_TENSOR_NUM) {
     175            1 :         IDE_LOGE("Extra tensor size exceeds the maximum limit. realSize=%u, maxSize=%u",
     176              :             info_.extraTensorNum, EXCEPTION_DUMP_MAX_TENSOR_NUM);
     177            1 :         return ADUMP_FAILED;
     178              :     }
     179              : 
     180            3 :     IDE_LOGI("Begin to dump extra tensors. extra tensor size=%u", info_.extraTensorNum);
     181              :         
     182            3 :     std::vector<DumpTensor> inputTensors;
     183            3 :     std::vector<DumpTensor> outputTensors;
     184            3 :     std::vector<DumpWorkspace> workspaces;
     185            3 :     uint32_t baseOffset = static_cast<uint32_t>(tensorBuffer_.size() + workspaces_.size());
     186              :     
     187            9 :     for (uint32_t i = 0; i < info_.extraTensorNum; ++i) {
     188            6 :         if (info_.extraTensor[i].tensorAddr == nullptr || info_.extraTensor[i].tensorSize == 0) {
     189            1 :             IDE_LOGW("Skip null extra tensor[%u], addr=%p, size=%zu.",
     190              :                      i, info_.extraTensor[i].tensorAddr, info_.extraTensor[i].tensorSize);
     191            1 :             continue;
     192              :         }
     193              :         // tensor基于args偏移offset
     194            5 :         info_.extraTensor[i].argsOffSet = baseOffset + i;
     195              :         
     196            5 :         RecordDumpLog(StrUtils::Format("[Dump][Exception] exception info dump extra tensor data, "
     197              :             "addr:%p; size:%zu bytes; index:%u(origin:%u); type:%d",
     198              :             info_.extraTensor[i].tensorAddr, info_.extraTensor[i].tensorSize,
     199            5 :             info_.extraTensor[i].argsOffSet, i, static_cast<int>(info_.extraTensor[i].type)));
     200              :         
     201            5 :         if (info_.extraTensor[i].type == TensorType::INPUT) {
     202            3 :             inputTensors.emplace_back(info_.extraTensor[i]);
     203            2 :         } else if (info_.extraTensor[i].type == TensorType::OUTPUT) {
     204            1 :             outputTensors.emplace_back(info_.extraTensor[i]);
     205            1 :         } else if (info_.extraTensor[i].type == TensorType::WORKSPACE) {
     206              :             DumpWorkspace workspace;
     207            1 :             workspace.addr = info_.extraTensor[i].tensorAddr;
     208            1 :             workspace.bytes = info_.extraTensor[i].tensorSize;
     209            1 :             workspace.argsOffset = info_.extraTensor[i].argsOffSet;
     210            1 :             workspaces.push_back(workspace);
     211              :         }
     212              :     }
     213              : 
     214            3 :     dumpFile_.SetInputTensors(inputTensors);
     215            3 :     dumpFile_.SetOutputTensors(outputTensors);
     216            3 :     dumpFile_.SetWorkspaces(workspaces);
     217              : 
     218            3 :     IDE_LOGI("End to dump extra tensors.");
     219            3 :     return ADUMP_SUCCESS;
     220            3 : }
     221              : 
     222            6 : int32_t DumpArgsCallback::Dump()
     223              : {
     224            6 :     int32_t ret = dumpFile_.Dump(logRecord_);
     225            6 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
     226              :         "[Dump][Exception] Write callback exception to file failed, file: %s", dumpFilePath_.c_str());
     227              : 
     228            5 :     (void)mmChmod(dumpFilePath_.c_str(), M_IRUSR);  // readonly, 400
     229            5 :     IDE_LOGE("[Dump][Exception] dump exception to file, file: %s", dumpFilePath_.c_str());
     230            5 :     return ADUMP_SUCCESS;
     231              : }
     232              : 
     233            5 : void DumpArgsCallback::RecordDumpLog(const std::string &log)
     234              : {
     235            5 :     IDE_LOGE("%s", log.c_str());
     236            5 :     logRecord_.emplace_back(log + "\n");
     237            5 : }
     238              : 
     239              : } // namespace Adx
        

Generated by: LCOV version 2.0-1