LCOV - code coverage report
Current view: top level - adump/exception - dump_args_callback.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.9 % 126 112
Test Date: 2026-08-31 10:09:28 Functions: 88.9 % 9 8

            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(
      23           25 :     const rtExceptionInfo& exception, const ExceptionDumpInfo& info, const std::string& dumpPath)
      24           25 :     : exception_(exception),
      25           25 :       info_(info),
      26           25 :       dumpPath_(dumpPath),
      27           25 :       dumpFilePath_(
      28           50 :           dumpPath + "/" + 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           25 : {}
      34              : 
      35            4 : int32_t DumpArgsCallback::DumpKernelBin()
      36              : {
      37            4 :     std::string kernelName(info_.kernelName);
      38            4 :     if (info_.bin == nullptr || kernelName.empty()) {
      39            3 :         return ADUMP_SUCCESS;
      40              :     }
      41            1 :     IDE_LOGI("Dump kernel bin file. bin=%p, kernelName=%s", info_.bin, kernelName.c_str());
      42            1 :     KernelInfoCollector collector;
      43            1 :     int32_t ret = collector.InitFromBinHandle(info_.bin, kernelName);
      44            1 :     IDE_CTRL_VALUE_FAILED(
      45              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED, "Init for dump kernel bin failed. ret=%d, bin=%p, kernelName=%s.",
      46              :         ret, info_.bin, kernelName.c_str());
      47              : 
      48            1 :     std::string hostOPath;
      49            1 :     ret = collector.DumpHostKernelBin(dumpPath_, hostOPath);
      50            1 :     IDE_CTRL_VALUE_WARN(
      51              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED, "DumpHostKernelBin failed, kernelName=%s.", kernelName.c_str());
      52              : 
      53            1 :     ret = collector.StartCollectKernel(dumpPath_);
      54            1 :     IDE_CTRL_VALUE_WARN(
      55              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED, "StartCollectKernel failed, kernelName=%s.", kernelName.c_str());
      56              : 
      57            1 :     IDE_LOGI("DumpKernelBin success, kernelName=%s.", kernelName.c_str());
      58            1 :     return ADUMP_SUCCESS;
      59            4 : }
      60              : 
      61            6 : int32_t DumpArgsCallback::DumpKernelErrorSymbols(ErrorLocation& outLocation)
      62              : {
      63            6 :     if (info_.bin == nullptr) {
      64            2 :         return ADUMP_SUCCESS;
      65              :     }
      66            4 :     KernelSymbolLocator locator;
      67            4 :     int32_t ret = locator.InitFromBinHandle(info_.bin);
      68            4 :     IDE_CTRL_VALUE_FAILED(
      69              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      70              :         "KernelSymbolLocator InitFromBinHandle failed for callback exception. ret=%d", ret);
      71            3 :     locator.UpdateStartPCFromDeviceAddr(info_.bin);
      72              : 
      73              :     // 回调路径的 _host.o 已由 DumpKernelBin 同步落盘,此处复用其路径决定 symbolize 用的 .o。
      74              :     // kernelName 是定长数组成员,不会为 nullptr;std::string 构造依赖其内部 '\0' 结尾。
      75            3 :     KernelInfoCollector collector;
      76            6 :     if (collector.InitFromBinHandle(info_.bin, std::string(info_.kernelName)) == ADUMP_SUCCESS) {
      77            3 :         const std::string hostOPath = collector.GetHostOFilePath(dumpPath_);
      78            3 :         locator.SetOFilePath(KernelSymbolLocator::ResolveOFilePath(hostOPath));
      79            3 :     }
      80              : 
      81            3 :     ExceptionRegInfo exceptionRegInfo{0, nullptr};
      82            3 :     ret = ExceptionInfoCommon::GetExceptionRegInfo(exception_, exceptionRegInfo);
      83            3 :     IDE_CTRL_VALUE_WARN(
      84              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      85              :         "Get exception register information failed for callback exception. ret=%d", ret);
      86              : 
      87              :     // 构建 ErrorLocation:LocateErrorSymbolsForCore 内部定位偏移后对该 .o 批量 symbolize 并回填 src。
      88            2 :     ret = locator.LocateErrorSymbolsForCore(info_.coreId, info_.coreType, exceptionRegInfo, outLocation);
      89            2 :     IDE_CTRL_VALUE_WARN(
      90              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED,
      91              :         "LocateErrorSymbolsForCore failed for callback exception. ret=%d, coreId=%u, coreType=%u.", ret, info_.coreId,
      92              :         info_.coreType);
      93              : 
      94            1 :     return ADUMP_SUCCESS;
      95            4 : }
      96              : 
      97            3 : int32_t DumpArgsCallback::QueryDfxIsTikInfo(rtFuncHandle funcHandle)
      98              : {
      99            3 :     size_t isTikSize = 0;
     100            3 :     rtError_t rtRet = rtFunctionGetMetaInfoSize(funcHandle, RT_FUNCTION_TYPE_L0_EXCEPTION_DFX_IS_TIK, &isTikSize);
     101            3 :     if (rtRet != RT_ERROR_NONE || isTikSize == 0 || isTikSize < sizeof(uint32_t)) {
     102            1 :         IDE_LOGW(
     103              :             "rtFunctionGetMetaInfoSize for dfxIsTik failed, will set dfxIsTik with false. "
     104              :             "rtRet=%d, kernelName=%s",
     105              :             rtRet, info_.kernelName);
     106            1 :         return ADUMP_FAILED;
     107              :     }
     108              : 
     109            2 :     std::vector<uint8_t> isTikBuffer(isTikSize);
     110            2 :     rtRet = rtFunctionGetMetaInfo(funcHandle, RT_FUNCTION_TYPE_L0_EXCEPTION_DFX_IS_TIK, isTikBuffer.data(), isTikSize);
     111            2 :     if (rtRet != RT_ERROR_NONE) {
     112            1 :         IDE_LOGW(
     113              :             "rtFunctionGetMetaInfo for isTik failed, will set dfxIsTik with false. "
     114              :             "ret=%d, kernelName=%s, isTikSize=%zu.",
     115              :             rtRet, info_.kernelName, isTikSize);
     116            1 :         return ADUMP_FAILED;
     117              :     }
     118              : 
     119            1 :     uint32_t isTik = 0;
     120            1 :     isTik = *reinterpret_cast<uint32_t*>(isTikBuffer.data());
     121            1 :     isTik_ = (isTik == 1U) ? true : false;
     122            1 :     IDE_LOGI("Query dfxIsTik info success. kernelName=%s, dfxIsTik=%u", info_.kernelName, isTik);
     123            1 :     return ADUMP_SUCCESS;
     124            2 : }
     125              : 
     126            7 : int32_t DumpArgsCallback::QueryDfxInfo(std::vector<uint8_t>& dfxBuffer)
     127              : {
     128            7 :     rtFuncHandle funcHandle = nullptr;
     129            7 :     rtError_t rtRet = rtBinaryGetFunctionByName(info_.bin, info_.kernelName, &funcHandle);
     130            7 :     IDE_CTRL_VALUE_FAILED(
     131              :         rtRet == RT_ERROR_NONE && funcHandle != nullptr, return ADUMP_FAILED,
     132              :         "rtBinaryGetFunctionByName failed, ret=%d, bin=%p, kernelName=%s.", rtRet, info_.bin, info_.kernelName);
     133              : 
     134            6 :     size_t dfxSize = 0;
     135            6 :     rtRet = rtFunctionGetMetaInfoSize(funcHandle, RT_FUNCTION_TYPE_DFX_TYPE, &dfxSize);
     136            6 :     IDE_CTRL_VALUE_FAILED(
     137              :         rtRet == RT_ERROR_NONE && dfxSize > 0, return ADUMP_FAILED,
     138              :         "rtFunctionGetMetaInfoSize failed, ret=%d, kernelName=%s, dfxSize=%zu.", rtRet, info_.kernelName, dfxSize);
     139            5 :     IDE_CTRL_VALUE_FAILED(
     140              :         dfxSize <= UINT16_MAX, return ADUMP_FAILED, "Dfx size exceeds uint16_t max, dfxSize=%zu", dfxSize);
     141              : 
     142            4 :     dfxBuffer.resize(dfxSize);
     143            4 :     rtRet = rtFunctionGetMetaInfo(funcHandle, RT_FUNCTION_TYPE_DFX_TYPE, dfxBuffer.data(), dfxSize);
     144            4 :     IDE_CTRL_VALUE_FAILED(
     145              :         rtRet == RT_ERROR_NONE, return ADUMP_FAILED,
     146              :         "rtFunctionGetMetaInfo failed, ret=%d, kernelName=%s, dfxSize=%zu.", rtRet, info_.kernelName, dfxSize);
     147              : 
     148            3 :     (void)QueryDfxIsTikInfo(funcHandle);
     149              : 
     150            3 :     IDE_LOGI(
     151              :         "Query kernel dfx args info success. kernelName=%s, dfxSize=%zu, isTik=%d", info_.kernelName, dfxSize, isTik_);
     152            3 :     return ADUMP_SUCCESS;
     153              : }
     154              : 
     155            9 : int32_t DumpArgsCallback::DumpDfxArgs()
     156              : {
     157              :     // kernelName 是定长数组成员,不会为 nullptr,直接判首字节是否为空串。
     158            9 :     if (info_.argAddr == nullptr || info_.argSize == 0 || info_.bin == nullptr || info_.kernelName[0] == '\0') {
     159            2 :         return ADUMP_SUCCESS;
     160              :     }
     161              : 
     162            7 :     IDE_LOGI(
     163              :         "Begin to dump dfx args tensors. argAddr=%p, argSize=%u, bin=%p, kernelName=%s", info_.argAddr, info_.argSize,
     164              :         info_.bin, info_.kernelName);
     165              : 
     166            7 :     int32_t ret = QueryDfxInfo(dfxBuffer_);
     167            7 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED, "Query kernel dfx info failed.");
     168              : 
     169            3 :     DfxArgsParser parser;
     170            3 :     ret = parser.Init(info_.argAddr, info_.argSize, dfxBuffer_.data(), static_cast<uint16_t>(dfxBuffer_.size()));
     171            3 :     IDE_CTRL_VALUE_FAILED(ret == ADUMP_SUCCESS, return ADUMP_FAILED, "Dfx args parser init failed.");
     172              : 
     173            3 :     parser.SetIsTik(isTik_);
     174            3 :     ret = parser.InitTensorModeInfo();
     175            3 :     IDE_CHECK_RET(ret, return ADUMP_FAILED);
     176              : 
     177            0 :     ret = parser.ParseAll();
     178            0 :     IDE_CHECK_RET(ret, return ADUMP_FAILED);
     179              : 
     180            0 :     tensorBuffer_ = parser.GetTensors();
     181            0 :     workspaces_ = parser.GetWorkspaces();
     182            0 :     logRecord_ = parser.GetLogRecords();
     183              : 
     184            0 :     IDE_LOGI(
     185              :         "Dfx args tensors are parsed finished. tensor size=%zu, workspace size=%zu.", tensorBuffer_.size(),
     186              :         workspaces_.size());
     187              : 
     188            0 :     dumpFile_.SetTensorBuffer(tensorBuffer_);
     189            0 :     dumpFile_.SetWorkspaces(workspaces_);
     190              : 
     191            0 :     IDE_LOGI("End to dump dfx args tensors.");
     192            0 :     return ADUMP_SUCCESS;
     193            3 : }
     194              : 
     195            6 : int32_t DumpArgsCallback::DumpExtraTensors()
     196              : {
     197            6 :     if (info_.extraTensorNum == 0) {
     198            2 :         return ADUMP_SUCCESS;
     199              :     }
     200            4 :     if (info_.extraTensorNum > EXCEPTION_DUMP_MAX_TENSOR_NUM) {
     201            1 :         IDE_LOGE(
     202              :             "Extra tensor size exceeds the maximum limit. realSize=%u, maxSize=%u", info_.extraTensorNum,
     203              :             EXCEPTION_DUMP_MAX_TENSOR_NUM);
     204            1 :         return ADUMP_FAILED;
     205              :     }
     206              : 
     207            3 :     IDE_LOGI("Begin to dump extra tensors. extra tensor size=%u", info_.extraTensorNum);
     208              : 
     209            3 :     const uint32_t baseOffset = static_cast<uint32_t>(tensorBuffer_.size() + workspaces_.size());
     210            3 :     std::vector<TensorInfo> tensors(info_.extraTensor, info_.extraTensor + info_.extraTensorNum);
     211            9 :     for (uint32_t i = 0; i < info_.extraTensorNum; ++i) {
     212            6 :         tensors[i].argsOffSet = baseOffset + i;
     213              :     }
     214            3 :     dumpFile_.SetTensors(tensors, logRecord_);
     215              : 
     216            3 :     IDE_LOGI("End to dump extra tensors.");
     217            3 :     return ADUMP_SUCCESS;
     218            3 : }
     219              : 
     220            6 : int32_t DumpArgsCallback::Dump()
     221              : {
     222            6 :     int32_t ret = dumpFile_.Dump(logRecord_);
     223            6 :     IDE_CTRL_VALUE_FAILED(
     224              :         ret == ADUMP_SUCCESS, return ADUMP_FAILED,
     225              :         "[Dump][Exception] Write callback exception to file failed, file: %s", dumpFilePath_.c_str());
     226              : 
     227            5 :     (void)mmChmod(dumpFilePath_.c_str(), M_IRUSR); // readonly, 400
     228            5 :     IDE_LOGE("[Dump][Exception] dump exception to file, file: %s", dumpFilePath_.c_str());
     229            5 :     return ADUMP_SUCCESS;
     230              : }
     231              : 
     232            0 : void DumpArgsCallback::RecordDumpLog(const std::string& log)
     233              : {
     234            0 :     IDE_LOGE("%s", log.c_str());
     235            0 :     logRecord_.emplace_back(log + "\n");
     236            0 : }
     237              : 
     238              : } // namespace Adx
        

Generated by: LCOV version 2.0-1