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

Generated by: LCOV version 2.0-1