LCOV - code coverage report
Current view: top level - adump/exception - exception_dumper.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.1 % 367 305
Test Date: 2026-08-12 11:04:53 Functions: 93.8 % 32 30

            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              : #include <set>
      11              : #include <cctype>
      12              : #include <cstring>
      13              : #include <algorithm>
      14              : #include "log/adx_log.h"
      15              : #include "path.h"
      16              : #include "dump_manager.h"
      17              : #include "dump_config_converter.h"
      18              : #include "sys_utils.h"
      19              : #include "dump_args.h"
      20              : #include "dump_args_callback.h"
      21              : #include "dump_file.h"
      22              : #include "exception_info_common.h"
      23              : #include "kernel_symbol_locator.h"
      24              : #include "kernel_info_collector.h"
      25              : #include "exception_dumper.h"
      26              : 
      27              : namespace Adx {
      28              : namespace {
      29              : constexpr char DEFAULT_DUMP_PATH[] = "./";
      30              : constexpr char EXTRA_DUMP_PATH[] = "/extra-info/data-dump/";
      31              : constexpr size_t MAX_DUMP_OP_NUM = (2048U * 2048U) / 20U;
      32              : 
      33           12 : static bool IsSafeKernelDisplayName(const char *name)
      34              : {
      35           77 :     for (size_t i = 0; i < MAX_KERNELNAME_LEN && name[i] != '\0'; ++i) {
      36           69 :         char c = name[i];
      37           69 :         if (c == '/' || c == '\\' || c < 0x20 || c == 0x7F) {
      38            4 :             return false;
      39              :         }
      40              :     }
      41           16 :     return std::string(name).find("..") == std::string::npos;
      42              : }
      43              : 
      44            7 : bool ValidateKernelName(const ExceptionDumpInfo &info)
      45              : {
      46            7 :     if (strnlen(info.kernelName, MAX_KERNELNAME_LEN) == MAX_KERNELNAME_LEN ||
      47            7 :         strnlen(info.kernelDisplayName, MAX_KERNELNAME_LEN) == MAX_KERNELNAME_LEN) {
      48            0 :         return false;
      49              :     }
      50              : 
      51            7 :     if (!IsSafeKernelDisplayName(info.kernelName) || !IsSafeKernelDisplayName(info.kernelDisplayName)) {
      52            4 :         return false;
      53              :     }
      54            3 :     return true;
      55              : }
      56              : 
      57            9 : bool IsValidExceptionDumpMode(ExceptionDumpMode dumpMode)
      58              : {
      59            8 :     return dumpMode == ExceptionDumpMode::DUMP_MODE_NONE ||
      60           17 :            dumpMode == ExceptionDumpMode::DUMP_MODE_OVERWRITE ||
      61            9 :            dumpMode == ExceptionDumpMode::DUMP_MODE_ADDITIONAL;
      62              : }
      63              : }  // namespace
      64              : 
      65              : uint64_t *g_dynamicChunk = nullptr;
      66              : uint64_t *g_staticChunk = nullptr;
      67              : 
      68           48 : ExceptionDumper::~ExceptionDumper()
      69              : {
      70           48 :     if (g_dynamicChunk != nullptr) {
      71           18 :         delete[] g_dynamicChunk;
      72           18 :         g_dynamicChunk = nullptr;
      73              :     }
      74              : 
      75           48 :     if (g_staticChunk != nullptr) {
      76           18 :         delete[] g_staticChunk;
      77           18 :         g_staticChunk = nullptr;
      78              :     }
      79           48 :     KernelSymbolLocator::ClearCache();
      80           48 :     destructionFlag_ = true;
      81           48 : }
      82              : 
      83           57 : bool ExceptionDumper::InitArgsExceptionMemory() const
      84              : {
      85           57 :     if (g_dynamicChunk == nullptr) {
      86      7149942 :         g_dynamicChunk = new (std::nothrow) uint64_t[DYNAMIC_RING_CHUNK_SIZE + DFX_MAX_TENSOR_NUM + RESERVE_SPACE]();
      87           18 :         if (g_dynamicChunk == nullptr) {
      88            0 :             return false;
      89              :         }
      90              :     }
      91              : 
      92           57 :     if (g_staticChunk == nullptr) {
      93      2431350 :         g_staticChunk = new (std::nothrow) uint64_t[STATIC_RING_CHUNK_SIZE + DFX_MAX_TENSOR_NUM + RESERVE_SPACE]();
      94           18 :         if (g_staticChunk == nullptr) {
      95            0 :             return false;
      96              :         }
      97              :     }
      98           57 :     return true;
      99              : }
     100              : 
     101          123 : bool ExceptionDumper::IsRepeatEnableException(DumpType type, const DumpConfig &dumpConfig)
     102              : {
     103          123 :     if (type == DumpType::ARGS_EXCEPTION || type == DumpType:: EXCEPTION ||
     104              :         type == DumpType::AIC_ERR_DETAIL_DUMP) {
     105           56 :         std::string dumpStatus = dumpConfig.dumpStatus;
     106           56 :         std::transform(dumpStatus.begin(), dumpStatus.end(), dumpStatus.begin(), ::tolower);
     107           56 :         if (dumpStatus != "on") {
     108           11 :             return false;
     109              :         }
     110           45 :         return IsEnabledExceptionDump();
     111           56 :     }
     112           67 :     return false;
     113              : }
     114              : 
     115          125 : bool ExceptionDumper::IsEnabledExceptionDump() const
     116              : {
     117          125 :     return coredumpStatus_ || exceptionStatus_ || argsExceptionStatus_;
     118              : }
     119              : 
     120           77 : int32_t ExceptionDumper::ExceptionDumperInit(DumpType dumpType, const DumpConfig &dumpConfig)
     121              : {
     122           77 :     bool status = false;
     123           77 :     if (!setting_.InitDumpStatus(dumpConfig.dumpStatus, status)) {
     124            1 :         IDE_LOGE("The value of dumpStatus: %s is invalid.", dumpConfig.dumpStatus.c_str());
     125            1 :         return ADUMP_FAILED;
     126              :     }
     127              : 
     128              :     // status = false means turn off, flag = false means not start, print warning when not start but want to turn off
     129           76 :     if (dumpType == DumpType::EXCEPTION) {
     130           13 :         IDE_CTRL_VALUE_WARN(status || exceptionStatus_, return ADUMP_SUCCESS, "dump type %d not start.", dumpType);
     131           12 :         exceptionStatus_ = status;
     132           63 :     } else if (dumpType == DumpType::ARGS_EXCEPTION) {
     133           57 :         IDE_CTRL_VALUE_WARN(status || argsExceptionStatus_, return ADUMP_SUCCESS, "dump type %d not start.", dumpType);
     134           53 :         IDE_CTRL_VALUE_FAILED(InitArgsExceptionMemory(), return ADUMP_FAILED, "Init args exception memory failed.");
     135           53 :         if (status && !argsExceptionStatus_) {
     136           47 :             IDE_CTRL_VALUE_WARN(LoadTensorPluginLib() == ADUMP_SUCCESS, return ADUMP_FAILED,
     137              :                 "Load tersor custom plugin failed.");
     138              :         }
     139           53 :         argsExceptionStatus_ = status;
     140              :     } else {
     141              :         // detail exception dump can not off
     142            6 :         if (status == false) {
     143              :             static bool havePrint = false;
     144            2 :             if (!havePrint) {
     145            1 :                 IDE_RUN_LOGI("Can not turn off detail exception dump.");
     146            1 :                 havePrint = true;
     147              :             }
     148            2 :             IDE_LOGW("Can not turn off detail exception dump.");
     149            2 :             return ADUMP_SUCCESS;
     150              :         }
     151            4 :         IDE_CTRL_VALUE_FAILED(InitArgsExceptionMemory(), return ADUMP_FAILED, "Init args exception memory failed.");
     152            4 :         coredumpStatus_ = true;
     153              :     }
     154              : 
     155           69 :     SetDumpPath(dumpConfig.dumpPath);
     156           69 :     return ADUMP_SUCCESS;
     157              : }
     158              : 
     159           61 : std::string ExceptionDumper::GetDumpSceneName() const
     160              : {
     161           61 :     if (coredumpStatus_) {
     162            3 :         return ADUMP_DUMP_EXCEPTION_AIC_ERR_DETAIL;
     163           58 :     } else if (exceptionStatus_) {
     164            1 :         return ADUMP_DUMP_EXCEPTION_AIC_ERR_NORM;
     165           57 :     } else if (argsExceptionStatus_) {
     166           57 :         return ADUMP_DUMP_EXCEPTION_AIC_ERR_BRIEF;
     167              :     } else {
     168            0 :         return "unknown";
     169              :     }
     170              : }
     171              : 
     172           82 : int32_t ExceptionDumper::DumpException(const rtExceptionInfo &exception)
     173              : {
     174           82 :     IDE_CTRL_VALUE_WARN(!destructionFlag_, return ADUMP_FAILED, "ExceptionDumper has been destructed.");
     175           82 :     IDE_CTRL_VALUE_WARN(ExceptionInfoCommon::IsSupportExceptionDump(exception),
     176              :         return ADUMP_FAILED, "Exception is not need to dump.");
     177           68 :     IDE_CTRL_VALUE_WARN(IsEnabledExceptionDump(), return ADUMP_FAILED,
     178              :         "Not enable exception dump.");
     179           66 :     std::string dumpPath = CreateDeviceDumpPath(exception.deviceid);
     180           66 :     if (dumpPath.empty()) {
     181            5 :         return ADUMP_FAILED;
     182              :     }
     183              : 
     184           61 :     const std::string dumpScene = GetDumpSceneName();
     185           61 :     const std::string exceptionType = ExceptionInfoCommon::GetExceptionTaskTypeName(exception);
     186           61 :     const std::string kernelName = ExceptionInfoCommon::GetExceptionKernelName(exception);
     187           61 :     IDE_LOGE("[Dump][Exception] Begin to dump exception. dumpScene=%s, deviceId=%u, streamId=%u, taskId=%u, "
     188              :         "exceptionType=%d(%s), kernelName=%s.", dumpScene.c_str(), exception.deviceid, exception.streamid,
     189              :         exception.taskid, static_cast<int32_t>(exception.expandInfo.type), exceptionType.c_str(),
     190              :         kernelName.c_str());
     191              : 
     192           61 :     if (coredumpStatus_) {
     193            3 :         return DumpDetailException(exception, dumpPath);
     194           58 :     } else if (exceptionStatus_) {
     195            1 :         return DumpNormalException(exception, dumpPath);
     196              :     } else {
     197           57 :         return DumpArgsException(exception, dumpPath);
     198              :     }
     199           66 : }
     200              : 
     201           69 : void ExceptionDumper::SetDumpPath(const std::string &dumpPath)
     202              : {
     203           86 :     dumpPath_ = dumpPath.empty() ? DEFAULT_DUMP_PATH : dumpPath;
     204           69 :     IDE_LOGI("Update exception dump path: %s", dumpPath_.c_str());
     205           69 : }
     206              : 
     207            4 : void ExceptionDumper::AddDumpOperator(const OperatorInfo &opInfo)
     208              : {
     209            4 :     OperatorInfoV2 dumpOperator = {};
     210            4 :     DumpManager::Instance().ConvertOperatorInfo(opInfo, dumpOperator);
     211            4 :     AddDumpOperatorV2(dumpOperator);
     212            4 : }
     213              : 
     214          118 : void ExceptionDumper::AddDumpOperatorV2(const OperatorInfoV2 &opInfo)
     215              : {
     216          118 :     const std::lock_guard<std::mutex> lock(mutex_);
     217          118 :     if (opInfo.agingFlag) {
     218            6 :         agingOperators_.emplace_back(opInfo);
     219            6 :         if (agingOperators_.size() > MAX_DUMP_OP_NUM) {
     220            0 :             agingOperators_.pop_front();
     221              :         }
     222              :     } else {
     223          112 :         uint32_t maxStreamCount = 0;
     224          112 :         uint32_t maxTaskCount = 0;
     225          112 :         rtGetMaxStreamAndTask(0, &maxStreamCount, &maxTaskCount);
     226          112 :         auto &taskDeque = residentOperators_[opInfo.deviceId][opInfo.streamId];
     227          112 :         taskDeque.emplace_back(opInfo);
     228          112 :         if (taskDeque.size() > maxTaskCount) {
     229            2 :             taskDeque.pop_front();
     230              :         }
     231              :     }
     232          118 :     IDE_LOGI("Dump operator size, aging: %zu, resident: %zu", agingOperators_.size(), residentOperators_.size());
     233          118 : }
     234              : 
     235            9 : int32_t ExceptionDumper::DelDumpOperator(uint32_t deviceId, uint32_t streamId)
     236              : {
     237            9 :     const std::lock_guard<std::mutex> lock(mutex_);
     238            9 :     auto it = residentOperators_.find(deviceId);
     239            9 :     if (it != residentOperators_.end()) {
     240            8 :         it->second.erase(streamId);
     241            8 :         if (it->second.empty()) {
     242            8 :             residentOperators_.erase(deviceId);
     243              :         }
     244              :     }
     245            9 :     return ADUMP_SUCCESS;
     246            9 : }
     247              : 
     248           96 : std::string ExceptionDumper::CreateDumpPath(Path &dumpPath) const
     249              : {
     250          116 :     IDE_CTRL_VALUE_FAILED(dumpPath.CreateDirectory(true), return "", "Create path[%s] failed",
     251              :         dumpPath.GetCString());
     252           94 :     IDE_CTRL_VALUE_FAILED(dumpPath.RealPath(), return "", "Get RealPath of [%s] failed, strerr=%s",
     253              :         dumpPath.GetCString(), strerror(errno));
     254           82 :     return dumpPath.GetString();
     255              : }
     256              : 
     257           90 : std::string ExceptionDumper::CreateDeviceDumpPath(uint32_t deviceId) const
     258              : {
     259              :     // Create device dump path when exception call-backed
     260           90 :     std::string dumpPath = dumpPath_.empty() ? DEFAULT_DUMP_PATH : dumpPath_;
     261           90 :     Path deviceDumpPath(dumpPath);
     262           90 :     deviceDumpPath.Append(EXTRA_DUMP_PATH).Append(std::to_string(deviceId));
     263          180 :     return CreateDumpPath(deviceDumpPath);
     264           90 : }
     265              : 
     266           24 : int32_t ExceptionDumper::GetExceptionDumpPath(std::string &path)
     267              : {
     268           24 :     int32_t deviceId = 0;
     269           24 :     const rtError_t rtRet = rtGetDevice(&deviceId);
     270           24 :     IDE_CTRL_VALUE_FAILED(rtRet == RT_ERROR_NONE, return ADUMP_FAILED,
     271              :         "rtGetDevice failed when get the exception root dump path, ret=%d.", static_cast<int32_t>(rtRet));
     272              : 
     273           24 :     path = CreateDeviceDumpPath(static_cast<uint32_t>(deviceId));
     274           24 :     IDE_CTRL_VALUE_FAILED(!path.empty(), return ADUMP_FAILED, "exception dump root path is not ready.");
     275           18 :     return ADUMP_SUCCESS;
     276              : }
     277              : 
     278           15 : int32_t ExceptionDumper::SaveExceptionInfo(const std::string &fileName, const std::string &userTag,
     279              :     const std::vector<TensorInfo> &tensors)
     280              : {
     281           15 :     std::string rootPath;
     282           15 :     IDE_CTRL_VALUE_FAILED(GetExceptionDumpPath(rootPath) == ADUMP_SUCCESS, return ADUMP_FAILED,
     283              :         "[SaveExceptionInfo] get exception dump root path failed.");
     284              : 
     285           12 :     std::string realFilePath;
     286           12 :     IDE_CTRL_VALUE_FAILED(Path::BuildFullPathUnderRoot(rootPath, fileName, realFilePath),
     287              :         return ADUMP_FAILED, "[SaveExceptionInfo] build full file path failed.");
     288              : 
     289           12 :     realFilePath += ".custom." + SysUtils::GetCurrentTimeWithMillisecond();
     290              : 
     291           12 :     int32_t devId = 0;
     292           12 :     const rtError_t rtRet = rtGetDevice(&devId);
     293           12 :     IDE_CTRL_VALUE_FAILED(rtRet == RT_ERROR_NONE, return ADUMP_FAILED,
     294              :         "[SaveExceptionInfo] rtGetDevice failed, ret=%d.", static_cast<int32_t>(rtRet));
     295              : 
     296           12 :     DumpFile dumpFile(static_cast<uint32_t>(devId), realFilePath);
     297           12 :     dumpFile.SetHeader(Path(realFilePath).GetFileName());
     298           12 :     if (!userTag.empty()) {
     299           18 :         dumpFile.SetOpAttr("user_tag", userTag);
     300              :     }
     301              : 
     302           12 :     std::vector<std::string> record;
     303           12 :     dumpFile.SetTensors(tensors, record);
     304              : 
     305           12 :     IDE_CTRL_VALUE_FAILED(dumpFile.Dump(record) == ADUMP_SUCCESS, return ADUMP_FAILED,
     306              :         "[SaveExceptionInfo] dump exception info to file failed, file: %s", realFilePath.c_str());
     307              : 
     308            9 :     (void)mmChmod(realFilePath.c_str(), M_IRUSR);
     309            9 :     IDE_LOGE("[Dump][Exception] dump custom exception to file, file: %s", realFilePath.c_str());
     310            9 :     return ADUMP_SUCCESS;
     311           15 : }
     312              : 
     313            6 : std::string ExceptionDumper::CreateExtraDumpPath()
     314              : {
     315              :     // Create extra dump path for tensor custom dump data
     316            6 :     std::string dumpPath = dumpPath_.empty() ? DEFAULT_DUMP_PATH : dumpPath_;
     317            6 :     Path extraDumpPath(dumpPath);
     318            6 :     extraDumpPath.Append(EXTRA_DUMP_PATH);
     319            6 :     extraDumpPath_ = CreateDumpPath(extraDumpPath);
     320           12 :     return extraDumpPath_;
     321            6 : }
     322              : 
     323            7 : const char* ExceptionDumper::GetExtraDumpCPath() const
     324              : {
     325            7 :     return extraDumpPath_.empty() ? nullptr : extraDumpPath_.c_str();
     326              : }
     327              : 
     328            0 : bool ExceptionDumper::FindExceptionOperator(const rtExceptionInfo &exception, DumpOperator &excOp)
     329              : {
     330            0 :     OpIdentity excOpIdentiy(exception.deviceid, exception.taskid, exception.streamid);
     331            0 :     if (exception.expandInfo.type == RT_EXCEPTION_FFTS_PLUS) {
     332            0 :         uint32_t contextId = static_cast<uint32_t>(exception.expandInfo.u.fftsPlusInfo.contextId);
     333            0 :         uint32_t threadId = static_cast<uint32_t>(exception.expandInfo.u.fftsPlusInfo.threadId);
     334            0 :         IDE_LOGI("ffts+ op context id: %u, thread id: %u.", contextId, threadId);
     335            0 :         excOpIdentiy.contextId = contextId;
     336              :     }
     337              : 
     338            0 :     const std::lock_guard<std::mutex> lock(mutex_);
     339            0 :     IDE_LOGI("Dump op size, aging:%zu, resident:%zu, target: %s", agingOperators_.size(), residentOperators_.size(),
     340              :              excOpIdentiy.GetString().c_str());
     341            0 :     for (const auto &op : agingOperators_) {
     342            0 :         if (op.IsBelongTo(excOpIdentiy)) {
     343            0 :             IDE_LOGI("Find exception op in aging list: %s", excOpIdentiy.GetString().c_str());
     344            0 :             excOp = op;
     345            0 :             return true;
     346              :         }
     347              :     }
     348              : 
     349            0 :     if (residentOperators_.find(excOpIdentiy.deviceId) != residentOperators_.end()) {
     350            0 :         auto &streamMap = residentOperators_[excOpIdentiy.deviceId];
     351            0 :         if (streamMap.find(excOpIdentiy.streamId) != streamMap.end()) {
     352            0 :             auto &taskDeque = streamMap[excOpIdentiy.streamId];
     353            0 :             for (const auto &op : taskDeque) {
     354            0 :                 if (op.IsBelongTo(excOpIdentiy)) {
     355            0 :                     IDE_LOGI("Find exception op in resident list: %s", excOpIdentiy.GetString().c_str());
     356            0 :                     excOp = op;
     357            0 :                     return true;
     358              :                 }
     359              :             }
     360              :         }
     361              :     }
     362              : 
     363            0 :     IDE_LOGW("Not find dump operator, target: %s", excOpIdentiy.GetString().c_str());
     364            0 :     return false;
     365            0 : }
     366              : 
     367           48 : void ExceptionDumper::DumpHostKernelBinBeforeSymbolize(const rtExceptionInfo &exception,
     368              :                                                        const std::string &dumpPath) const
     369              : {
     370           48 :     rtExceptionArgsInfo_t exceptionArgsInfo{};
     371           48 :     int32_t ret = ExceptionInfoCommon::GetExceptionInfo(exception, exceptionArgsInfo);
     372           48 :     IDE_CTRL_VALUE_WARN(ret == ADUMP_SUCCESS, return,
     373              :         "Get exception args info failed, skip early dump host kernel bin.");
     374              : 
     375           48 :     KernelInfoCollector collector;
     376           48 :     collector.LoadKernelInfo(exceptionArgsInfo);
     377           48 :     ret = collector.LoadKernelBinBuffer();
     378           48 :     IDE_CTRL_VALUE_WARN(ret == ADUMP_SUCCESS, return,
     379              :         "Load kernel bin buffer failed, skip early dump host kernel bin.");
     380              : 
     381              :     // 提前同步落 _host.o;DumpHostKernelBin 幂等,后置慢搜索路径已存在则会跳过。
     382           48 :     (void)collector.DumpHostKernelBin(dumpPath);
     383           48 : }
     384              : 
     385            1 : int32_t ExceptionDumper::DumpNormalException(const rtExceptionInfo &exception, const std::string &dumpPath)
     386              : {
     387            1 :     IDE_CTRL_VALUE_WARN(ExceptionInfoCommon::IsSupportDefaultExceptionDump(exception),
     388              :         return ADUMP_FAILED, "Exception is not support default dump.");
     389            0 :     DumpHostKernelBinBeforeSymbolize(exception, dumpPath);
     390            0 :     KernelSymbolLocator::DumpErrorSymbols(exception);
     391            0 :     DumpOperator excOp;
     392            0 :     bool find = FindExceptionOperator(exception, excOp);
     393            0 :     if (!find) {
     394            0 :         return ADUMP_SUCCESS;
     395              :     }
     396              : 
     397            0 :     rtExceptionArgsInfo_t exceptionArgsInfo{};
     398            0 :     if (ExceptionInfoCommon::GetExceptionInfo(exception, exceptionArgsInfo) != ADUMP_SUCCESS) {
     399            0 :         IDE_LOGW("Get exception args info failed.");
     400            0 :         return ADUMP_FAILED;
     401              :     }
     402            0 :     (void)excOp.RefreshAddrs(exceptionArgsInfo);
     403            0 :     (void)excOp.LogExceptionInfo(exceptionArgsInfo);
     404            0 :     (void)excOp.CopyOpKernelFile();
     405              : 
     406            0 :     const int32_t ret = excOp.DumpException(exception.deviceid, dumpPath);
     407            0 :     if (ret != ADUMP_SUCCESS) {
     408            0 :         return ADUMP_FAILED;
     409              :     }
     410            0 :     return ADUMP_SUCCESS;
     411            0 : }
     412              : 
     413           49 : int32_t ExceptionDumper::DumpArgsExceptionDefault(const rtExceptionInfo &exception, const std::string &dumpPath)
     414              : {
     415           49 :     IDE_CTRL_VALUE_WARN(ExceptionInfoCommon::IsSupportDefaultExceptionDump(exception),
     416              :         return ADUMP_FAILED, "Exception is not support default dump.");
     417           48 :     DumpHostKernelBinBeforeSymbolize(exception, dumpPath);
     418           48 :     KernelSymbolLocator::DumpErrorSymbols(exception);
     419           48 :     DumpArgs args;
     420           48 :     if (args.LoadArgsExceptionInfo(exception) != ADUMP_SUCCESS) {
     421           30 :         return ADUMP_FAILED;
     422              :     }
     423              : 
     424           18 :     if (args.DumpArgsExceptionInfo(exception.deviceid, dumpPath) != ADUMP_SUCCESS) {
     425            0 :         return ADUMP_FAILED;
     426              :     }
     427           18 :     return ADUMP_SUCCESS;
     428           48 : }
     429              : 
     430           56 : int32_t ExceptionDumper::DumpArgsExceptionInner(const rtExceptionInfo &exception, const std::string &dumpPath)
     431              : {
     432           56 :     ExceptionDumpMode dumpMode = ExceptionDumpMode::DUMP_MODE_NONE;
     433           56 :     std::vector<ExceptionDumpInfo> dumpInfos;
     434           56 :     int32_t invokeRet = InvokeCallbacks(exception, dumpInfos, dumpMode);
     435           56 :     if (invokeRet != ADUMP_SUCCESS) {
     436            0 :         return invokeRet;
     437              :     }
     438           56 :     if (dumpMode == ExceptionDumpMode::DUMP_MODE_OVERWRITE) {
     439            5 :         if (dumpInfos.empty()) {
     440            3 :             IDE_LOGE("OVERWRITE mode with empty callback data after validation, reject.");
     441            3 :             return ADUMP_FAILED;
     442              :         }
     443            2 :         IDE_LOGI("DumpMode of callbacks is OVERWRITE, skip default dump, dump callback data only.");
     444            2 :         DumpCallbackData(exception, dumpInfos, dumpPath);
     445            2 :         return ADUMP_SUCCESS;
     446              :     }
     447              : 
     448           51 :     if (dumpMode == ExceptionDumpMode::DUMP_MODE_ADDITIONAL) {
     449            2 :         if (!dumpInfos.empty()) {
     450            1 :             IDE_LOGI("DumpMode of callbacks is ADDITIONAL, dump callback data and default.");
     451            1 :             DumpCallbackData(exception, dumpInfos, dumpPath);
     452              :         }
     453              :     }
     454              : 
     455           51 :     return DumpArgsExceptionDefault(exception, dumpPath);
     456           56 : }
     457              : 
     458           56 : int32_t ExceptionDumper::InvokeCallbacks(const rtExceptionInfo &exception,
     459              :                                          std::vector<ExceptionDumpInfo> &dumpInfos,
     460              :                                          ExceptionDumpMode &dumpMode)
     461              : {
     462           56 :     dumpMode = ExceptionDumpMode::DUMP_MODE_NONE;
     463           56 :     dumpInfos.clear();
     464              :     
     465           56 :     std::lock_guard<std::recursive_mutex> lock(callbackMutex_);
     466           56 :     if (callbacks_.empty()) {
     467           47 :         IDE_LOGI("No exception callbacks registered.");
     468           47 :         return ADUMP_SUCCESS;
     469              :     }
     470              : 
     471            9 :     ExceptionRegInfo exceptionRegInfo{0, nullptr};
     472            9 :     int32_t ret = ExceptionInfoCommon::GetExceptionRegInfo(exception, exceptionRegInfo);
     473            9 :     IDE_CTRL_VALUE_WARN(ret == ADUMP_SUCCESS, return ADUMP_FAILED,
     474              :         "GetExceptionRegInfo failed, ret=%d, coreNum=%u.", ret, exceptionRegInfo.coreNum);
     475              :     
     476            9 :     uint32_t maxDumpSize = exceptionRegInfo.coreNum == 0 ? 1 : exceptionRegInfo.coreNum;
     477            9 :     IDE_LOGI("Exception callbacks size=%zu, maxDumpSize=%u.", callbacks_.size(), maxDumpSize);
     478              :     
     479           18 :     for (auto &callback : callbacks_) {       
     480            9 :         std::vector<ExceptionDumpInfo> cbDumpInfos(maxDumpSize);
     481              :         
     482            9 :         uint32_t cbDumpRealSize = 0;
     483            9 :         ExceptionDumpMode cbDumpMode = ExceptionDumpMode::DUMP_MODE_NONE;
     484              : 
     485            9 :         uint32_t ret = callback(reinterpret_cast<void*>(const_cast<rtExceptionInfo*>(&exception)), cbDumpInfos.data(),
     486              :                                 maxDumpSize, &cbDumpRealSize, &cbDumpMode);
     487            9 :         if (ret != ADUMP_SUCCESS) {
     488            0 :             IDE_LOGW("Callback execute failed. ret=%u", ret);
     489            0 :             continue;
     490              :         }
     491            9 :         if (!IsValidExceptionDumpMode(cbDumpMode)) {
     492            1 :             IDE_LOGW("Callback dumpMode invalid. dumpMode=%u", static_cast<uint32_t>(cbDumpMode));
     493            1 :             continue;
     494              :         }
     495            8 :         if (cbDumpRealSize == 0 || cbDumpRealSize > maxDumpSize) {
     496            1 :             IDE_LOGW("Callback dumpRealSize invalid. maxDumpSize=%u, dumpRealSize=%u", maxDumpSize, cbDumpRealSize);
     497            1 :             continue;
     498              :         }
     499              : 
     500            7 :         IDE_LOGI("Callback dumpRealSize=%u, dumpMode=%d.", cbDumpRealSize, cbDumpMode);
     501           14 :         for (uint32_t i = 0; i < cbDumpRealSize; ++i) {
     502            7 :             if (!ValidateKernelName(cbDumpInfos[i])) {
     503            4 :                 IDE_LOGW("Invalid kernelName/kernelDisplayName in callback data, skip. index=%u", i);
     504            4 :                 continue;
     505              :             }
     506            3 :             dumpInfos.push_back(cbDumpInfos[i]);
     507              :         }
     508              :         
     509              :         // 多回调聚合时取优先级最高者:ADDITIONAL > OVERWRITE > NONE
     510            7 :         if (static_cast<uint32_t>(cbDumpMode) > static_cast<uint32_t>(dumpMode)) {
     511            7 :             dumpMode = cbDumpMode;
     512              :         }
     513            9 :     }
     514              :     
     515            9 :     IDE_LOGI("Callback final dumpMode=%d, dumpInfo total size=%zu.", dumpMode, dumpInfos.size());
     516            9 :     return ADUMP_SUCCESS;
     517           56 : }
     518              : 
     519            1 : void ExceptionDumper::DumpCallbackData(const rtExceptionInfo &exception,
     520              :                                        const std::vector<ExceptionDumpInfo> &dumpInfos,
     521              :                                        const std::string &dumpPath)
     522              : {
     523            2 :     for (const auto &info : dumpInfos) {
     524            1 :         IDE_LOGE("[Dump][Exception] Begin to dump callback exception. coreType=%u, coreId=%u, "
     525              :             "argAddr=%p, argSize=%u, binHandle=%p, extraTensorNum=%u, kernelName=%s.",
     526              :             info.coreType, info.coreId, info.argAddr, info.argSize, info.bin, info.extraTensorNum, info.kernelName);
     527            1 :         IDE_LOGE("[Dump][Exception] Callback exception. kernelDisplayName=%s.", info.kernelDisplayName);
     528            1 :         DumpArgsCallback argsCallback(exception, info, dumpPath);
     529            1 :         int32_t ret = argsCallback.DumpDfxArgs();
     530            1 :         if (ret != ADUMP_SUCCESS) {
     531            0 :             IDE_LOGW("Dump callback args failed.");
     532              :         }
     533              : 
     534            1 :         ret = argsCallback.DumpExtraTensors();
     535            1 :         if (ret != ADUMP_SUCCESS) {
     536            0 :             IDE_LOGW("Dump callback extra tensor failed.");
     537              :         }
     538              : 
     539            1 :         ret = argsCallback.Dump();
     540            1 :         if (ret != ADUMP_SUCCESS) {
     541            0 :             IDE_LOGW("Dump callback data to file failed.");
     542              :         }
     543              : 
     544            1 :         ret = argsCallback.DumpKernelBin();
     545            1 :         if (ret != ADUMP_SUCCESS) {
     546            0 :             IDE_LOGW("Dump callback kernel bin failed.");
     547              :         }
     548              : 
     549            1 :         ret = argsCallback.DumpKernelErrorSymbols();
     550            1 :         if (ret != ADUMP_SUCCESS) {
     551            0 :             IDE_LOGW("Dump callback kernel error symbols failed.");
     552              :         }
     553              : 
     554            1 :         IDE_LOGI("Dump callback data finished, kernelName=%s.", info.kernelName);
     555            1 :     }
     556            1 :     KernelSymbolLocator::ClearCache();
     557            1 :     IDE_LOGI("Dump all callback data success.");
     558            1 : }
     559              : 
     560            5 : void ExceptionDumper::ExceptionModeDowngrade()
     561              : {
     562            5 :     coredumpEnableComplete_ = false;
     563            5 : }
     564              : 
     565            0 : void ExceptionDumper::Exit() const
     566              : {
     567            0 :     IDE_LOGE("The process exits.");
     568            0 :     AdxLogFlush();
     569              : #ifndef __ADUMP_LLT
     570              :     _exit(EXIT_FAILURE);
     571              : #endif
     572            0 : }
     573              : 
     574              : #ifdef __ADUMP_LLT
     575          644 : void ExceptionDumper::Reset()
     576              : {
     577          644 :     const std::lock_guard<std::mutex> lock(mutex_);
     578          644 :     agingOperators_.clear();
     579          644 :     residentOperators_.clear();
     580          644 :     exceptionStatus_ = false;
     581          644 :     argsExceptionStatus_ = false;
     582          644 :     coredumpStatus_ = false;
     583          644 :     coredumpEnableComplete_ = true;
     584          644 : }
     585              : #endif
     586              : 
     587           32 : int32_t ExceptionDumper::RegisterExceptionDumpCallback(ExceptionDumpCallback callback)
     588              : {
     589           32 :     if (callback == nullptr) {
     590            7 :         IDE_LOGE("Register callback is nullptr.");
     591            7 :         return ADUMP_INPUT_FAILED;
     592              :     }
     593              :     
     594           25 :     const std::lock_guard<std::recursive_mutex> lock(callbackMutex_);
     595           25 :     for (auto &cb : callbacks_) {
     596            4 :         if (cb == callback) {
     597            4 :             IDE_LOGW("Callback already registered.");
     598            4 :             return ADUMP_SUCCESS;
     599              :         }
     600              :     }
     601           21 :     callbacks_.push_back(callback);
     602           21 :     IDE_LOGI("Callback registered, total=%zu.", callbacks_.size());
     603           21 :     return ADUMP_SUCCESS;
     604           25 : }
     605              : 
     606           21 : int32_t ExceptionDumper::UnregisterExceptionDumpCallback(ExceptionDumpCallback callback)
     607              : {
     608           21 :     if (callback == nullptr) {
     609            7 :         IDE_LOGE("Unregister callback is nullptr.");
     610            7 :         return ADUMP_INPUT_FAILED;
     611              :     }
     612              :     
     613           14 :     const std::lock_guard<std::recursive_mutex> lock(callbackMutex_);
     614           14 :     for (auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
     615           10 :         if (*it == callback) {
     616           10 :             callbacks_.erase(it);
     617           10 :             IDE_LOGI("Callback unregistered, total=%zu.", callbacks_.size());
     618           10 :             return ADUMP_SUCCESS;
     619              :         }
     620              :     }
     621            4 :     IDE_LOGW("Callback not found.");
     622            4 :     return ADUMP_SUCCESS;
     623           14 : }
     624              : 
     625              : }  // namespace Adx
        

Generated by: LCOV version 2.0-1