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 <atomic>
11 : #include "acl_dump.h"
12 : #include "adump_pub.h"
13 : #include "adump_api.h"
14 : #include "dump_manager.h"
15 : #include "dump_printf.h"
16 : #include "adump_error_manager.h"
17 : #include "str_utils.h"
18 : #include "common/path.h"
19 :
20 : namespace Adx {
21 : uint64_t g_chunk[RING_CHUNK_SIZE + MAX_TENSOR_NUM] = {0};
22 : bool g_setAssert = false;
23 : static std::mutex g_setAssertMtx;
24 : namespace {
25 : uint32_t g_atomicIndex = 0x2000;
26 : std::atomic<uint64_t> g_writeIdx{0};
27 :
28 24 : void ConvertAclDumpTensorInner(const acldumpTensorInfo &src, size_t index, TensorInfo &dst)
29 : {
30 24 : dst.type = static_cast<TensorType>(src.type);
31 24 : dst.tensorSize = src.tensorSize;
32 24 : dst.format = src.format;
33 24 : dst.dataType = src.dataType;
34 24 : dst.tensorAddr = src.tensorAddr;
35 24 : dst.addrType = static_cast<AddressType>(src.addrType);
36 24 : dst.placement = static_cast<int32_t>(src.placement);
37 24 : dst.argsOffSet = static_cast<uint32_t>(index);
38 :
39 72 : for (uint32_t i = 0; i < src.shapeNum; ++i) {
40 48 : dst.shape.emplace_back(static_cast<int64_t>(src.shape[i]));
41 : }
42 72 : for (uint32_t i = 0; i < src.originShapeNum; ++i) {
43 48 : dst.originShape.emplace_back(static_cast<int64_t>(src.originShape[i]));
44 : }
45 24 : }
46 :
47 27 : bool ReportInvalidTensorField(size_t index, const char *field, const std::string &reason)
48 : {
49 27 : std::string param = StrUtils::Format("tensors[%zu].%s", index, field);
50 621 : REPORT_EP0006_INVALID_ARGUMENT(FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, param,
51 : FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_TENSORS, reason);
52 27 : return false;
53 81 : }
54 :
55 18 : bool ReportUnsupportedTensorField(size_t index, const char *field, int32_t value, const char *expected)
56 : {
57 18 : return ReportInvalidTensorField(index, field,
58 36 : StrUtils::Format(ADUMP_REASON_PARAM_VALUE_NOT_SUPPORTED, std::to_string(value).c_str(), expected));
59 : }
60 :
61 57 : bool CheckAclDumpTensorShape(const acldumpTensorInfo &src, size_t index)
62 : {
63 57 : const std::string maxShapeNum = std::to_string(ACL_DUMP_MAX_SHAPE_NUM);
64 57 : if (src.shapeNum > ACL_DUMP_MAX_SHAPE_NUM) {
65 3 : return ReportInvalidTensorField(index, "shapeNum",
66 9 : StrUtils::Format(ADUMP_REASON_PARAM_VALUE_EXCEED_LIMIT,
67 9 : std::to_string(src.shapeNum).c_str(), maxShapeNum.c_str()));
68 : }
69 54 : if (src.originShapeNum > ACL_DUMP_MAX_SHAPE_NUM) {
70 3 : return ReportInvalidTensorField(index, "originShapeNum",
71 9 : StrUtils::Format(ADUMP_REASON_PARAM_VALUE_EXCEED_LIMIT,
72 9 : std::to_string(src.originShapeNum).c_str(), maxShapeNum.c_str()));
73 : }
74 51 : return true;
75 57 : }
76 :
77 51 : bool CheckAclDumpTensorEnum(const acldumpTensorInfo &src, size_t index)
78 : {
79 51 : if (src.type != ACL_DUMP_TENSOR_INPUT
80 12 : && src.type != ACL_DUMP_TENSOR_OUTPUT
81 6 : && src.type != ACL_DUMP_TENSOR_WORKSPACE) {
82 3 : return ReportUnsupportedTensorField(index, "type", static_cast<int32_t>(src.type),
83 3 : "ACL_DUMP_TENSOR_INPUT/ACL_DUMP_TENSOR_OUTPUT/ACL_DUMP_TENSOR_WORKSPACE");
84 : }
85 48 : if (src.addrType != ACL_DUMP_ADDR_RAW) {
86 18 : return ReportUnsupportedTensorField(
87 9 : index, "addrType", static_cast<int32_t>(src.addrType), "ACL_DUMP_ADDR_RAW");
88 : }
89 39 : if (src.placement != ACL_DUMP_PLACEMENT_DEVICE) {
90 12 : return ReportUnsupportedTensorField(
91 6 : index, "placement", static_cast<int32_t>(src.placement), "ACL_DUMP_PLACEMENT_DEVICE");
92 : }
93 33 : return true;
94 : }
95 :
96 33 : bool CheckAclDumpTensorData(const acldumpTensorInfo &src, size_t index)
97 : {
98 33 : if (src.tensorAddr == nullptr) {
99 6 : std::string param = StrUtils::Format("tensors[%zu].tensorAddr", index);
100 90 : REPORT_EP0007_NULL_POINTER(FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, param);
101 6 : return false;
102 6 : }
103 27 : if (src.tensorSize == 0) {
104 3 : return ReportInvalidTensorField(
105 6 : index, "tensorSize", StrUtils::Format(ADUMP_REASON_PARAM_MUST_BE_GREATER_THAN, "0"));
106 : }
107 24 : return true;
108 12 : }
109 :
110 57 : bool ConvertAclDumpTensor(const acldumpTensorInfo &src, size_t index, TensorInfo &dst)
111 : {
112 57 : if (!CheckAclDumpTensorShape(src, index)
113 51 : || !CheckAclDumpTensorEnum(src, index)
114 108 : || !CheckAclDumpTensorData(src, index)) {
115 33 : return false;
116 : }
117 :
118 24 : ConvertAclDumpTensorInner(src, index, dst);
119 24 : return true;
120 : }
121 : } // namespace
122 :
123 45022 : void *AdumpGetSizeInfoAddr(uint32_t space, uint32_t &atomicIndex)
124 : {
125 45022 : if (!g_setAssert) {
126 3 : const std::lock_guard<std::mutex> lock(g_setAssertMtx);
127 3 : if (!g_setAssert) {
128 3 : (void)rtSetTaskFailCallback(AdxAssertCallBack);
129 3 : g_setAssert = true;
130 : }
131 3 : }
132 45022 : if (space > MAX_TENSOR_NUM) {
133 3 : return nullptr;
134 : }
135 :
136 45019 : atomicIndex = g_atomicIndex++;
137 45019 : auto nextWriteCursor = g_writeIdx.fetch_add(space);
138 45019 : return g_chunk + (nextWriteCursor % RING_CHUNK_SIZE);
139 : }
140 :
141 18 : int32_t AdumpRegisterCallback(uint32_t moduleId, AdumpCallback enableFunc, AdumpCallback disableFunc)
142 : {
143 18 : return DumpManager::Instance().RegisterCallback(moduleId, enableFunc, disableFunc);
144 : }
145 :
146 24 : int32_t AdumpSaveToFile(const char *data, size_t dataLen, const char *filename, SaveType type)
147 : {
148 24 : return DumpManager::Instance().SaveFile(data, dataLen, filename, type);
149 : }
150 : } // namespace Adx
151 :
152 : /**
153 : * @ingroup AscendCL
154 : * @brief Enable the dump function of the corresponding dump type.
155 : *
156 : * @param dumpType [IN] type of dump
157 : * @param path [IN] dump path
158 : *
159 : * @retval ACL_SUCCESS The function is successfully executed.
160 : * @retval OtherValues Failure
161 : */
162 30 : aclError aclopStartDumpArgs(uint32_t dumpType, const char *path)
163 : {
164 30 : if (path == nullptr) {
165 54 : REPORT_EP0007_NULL_POINTER(
166 : Adx::FUNC_NAME_ACL_OP_START_DUMP_ARGS, Adx::FUNC_ACL_OP_START_DUMP_ARGS_PARAM_PATH);
167 3 : return ACL_ERROR_FAILURE;
168 : }
169 :
170 27 : if ((dumpType & ACL_OP_DUMP_OP_AICORE_ARGS) != ACL_OP_DUMP_OP_AICORE_ARGS) {
171 6 : std::string dumpTypeStr = std::to_string(dumpType);
172 6 : std::string expTypeStr = std::to_string(ACL_OP_DUMP_OP_AICORE_ARGS);
173 : std::string reason = Adx::StrUtils::Format(
174 6 : Adx::ADUMP_REASON_RESERVED_PARAM_MUST_EQUAL, expTypeStr.c_str());
175 138 : REPORT_EP0006_INVALID_ARGUMENT(
176 : Adx::FUNC_NAME_ACL_OP_START_DUMP_ARGS, dumpTypeStr,
177 : Adx::FUNC_ACL_OP_START_DUMP_ARGS_PARAM_DUMPTYPE, reason);
178 6 : return ACL_ERROR_FAILURE;
179 6 : }
180 :
181 21 : std::string dumpPath(path);
182 21 : int32_t ret = Adx::DumpManager::Instance().StartDumpArgs(dumpPath);
183 21 : if (ret != 0) {
184 15 : return ACL_ERROR_FAILURE;
185 : }
186 :
187 6 : return ACL_SUCCESS;
188 33 : }
189 :
190 : /**
191 : * @ingroup AscendCL
192 : * @brief Disable the dump function of the corresponding dump type.
193 : *
194 : * @param dumpType [IN] type of dump
195 : *
196 : * @retval ACL_SUCCESS The function is successfully executed.
197 : * @retval OtherValues Failure
198 : */
199 15 : aclError aclopStopDumpArgs(uint32_t dumpType)
200 : {
201 15 : if ((dumpType & ACL_OP_DUMP_OP_AICORE_ARGS) == ACL_OP_DUMP_OP_AICORE_ARGS) {
202 15 : if (Adx::DumpManager::Instance().StopDumpArgs() != 0) {
203 3 : return ACL_ERROR_FAILURE;
204 : }
205 : }
206 12 : return ACL_SUCCESS;
207 : }
208 :
209 : /**
210 : * @ingroup AscendCL
211 : * @brief Get Exception Dump path.
212 : *
213 : * @retval path for success
214 : * @retval NULL for failed
215 : */
216 12 : const char* acldumpGetPath(acldumpType dumpType)
217 : {
218 12 : switch (dumpType) {
219 6 : case acldumpType::AIC_ERR_BRIEF_DUMP:
220 : case acldumpType::AIC_ERR_NORM_DUMP:
221 : case acldumpType::AIC_ERR_DETAIL_DUMP:
222 6 : return Adx::DumpManager::Instance().GetExtraExceptionDumpPath();
223 3 : case acldumpType::DATA_DUMP:
224 : case acldumpType::OVERFLOW_DUMP:
225 3 : return Adx::DumpManager::Instance().GetDataDumpPath();
226 3 : default:
227 3 : return nullptr;
228 : }
229 : }
230 :
231 : /**
232 : * @ingroup AscendCL
233 : * @brief Save custom exception info (tensors) to the Exception Dump path.
234 : * @retval ACL_SUCCESS The function is successfully executed.
235 : * @retval OtherValues Failure
236 : */
237 66 : aclError acldumpSaveExceptionInfo(const char *fileName, const char *userTag,
238 : const acldumpTensorInfo *tensors, size_t tensorCount)
239 : {
240 66 : if (fileName == nullptr) {
241 54 : REPORT_EP0007_NULL_POINTER(
242 : Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_FILENAME);
243 3 : return ACL_ERROR_INVALID_PARAM;
244 : }
245 :
246 63 : if (fileName[0] == '\0') {
247 78 : REPORT_EP0006_INVALID_ARGUMENT(Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, "",
248 : Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_FILENAME, Adx::ADUMP_REASON_PARAM_PATH_EMPTY);
249 3 : return ACL_ERROR_INVALID_PARAM;
250 : }
251 :
252 120 : if (Adx::Path::HasParentDirSegment(fileName)) {
253 156 : REPORT_EP0006_INVALID_ARGUMENT(Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, fileName,
254 : Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_FILENAME, Adx::ADUMP_REASON_PARAM_PATH_HAS_PARENT_DIR);
255 6 : return ACL_ERROR_INVALID_PARAM;
256 : }
257 :
258 54 : if (tensors == nullptr) {
259 54 : REPORT_EP0007_NULL_POINTER(
260 : Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_TENSORS);
261 3 : return ACL_ERROR_INVALID_PARAM;
262 : }
263 :
264 51 : if (tensorCount == 0) {
265 3 : const std::string reason = Adx::StrUtils::Format(Adx::ADUMP_REASON_PARAM_MUST_BE_GREATER_THAN, "0");
266 69 : REPORT_EP0006_INVALID_ARGUMENT(Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, std::to_string(tensorCount),
267 : Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_TENSORCOUNT, reason);
268 3 : return ACL_ERROR_INVALID_PARAM;
269 3 : }
270 :
271 48 : if (!Adx::DumpManager::Instance().IsEnabledExceptionDump()) {
272 : const std::string reason = Adx::StrUtils::Format(
273 0 : Adx::ADUMP_REASON_EXCEPTION_DUMP_NOT_ENABLED, Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO);
274 0 : REPORT_EP0008_API_CALL_SEQUENCE(Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, reason);
275 0 : return ACL_ERROR_FAILURE;
276 0 : }
277 :
278 48 : std::vector<Adx::TensorInfo> tensorInfos(tensorCount);
279 72 : for (size_t i = 0; i < tensorCount; ++i) {
280 57 : if (!Adx::ConvertAclDumpTensor(tensors[i], i, tensorInfos[i])) {
281 33 : return ACL_ERROR_INVALID_PARAM;
282 : }
283 : }
284 :
285 15 : const std::string userTagStr = (userTag == nullptr) ? "" : userTag;
286 30 : const int32_t ret = Adx::DumpManager::Instance().SaveExceptionInfo(fileName, userTagStr, tensorInfos);
287 15 : return ret == 0 ? ACL_SUCCESS : ACL_ERROR_FAILURE;
288 72 : }
289 :
290 : /**
291 : * @ingroup AscendCL
292 : * @brief Get the Exception Dump root path({dump_path}/extra-info/data-dump/{deviceId}/).
293 : * @retval ACL_SUCCESS The function is successfully executed.
294 : * @retval OtherValues Failure
295 : */
296 21 : aclError acldumpGetExceptionInfoPath(char *path, size_t maxLen)
297 : {
298 21 : if (path == nullptr) {
299 54 : REPORT_EP0007_NULL_POINTER(
300 : Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, Adx::FUNC_ACL_DUMP_GET_EXCEPTION_INFO_PATH_PARAM_PATH);
301 3 : return ACL_ERROR_INVALID_PARAM;
302 : }
303 18 : if (maxLen <= 1) {
304 6 : std::string reason = Adx::StrUtils::Format(Adx::ADUMP_REASON_PARAM_MUST_BE_GREATER_THAN, "1");
305 138 : REPORT_EP0006_INVALID_ARGUMENT(Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, std::to_string(maxLen),
306 : Adx::FUNC_ACL_DUMP_GET_EXCEPTION_INFO_PATH_PARAM_MAXLEN, reason);
307 6 : return ACL_ERROR_INVALID_PARAM;
308 6 : }
309 :
310 12 : if (!Adx::DumpManager::Instance().IsEnabledExceptionDump()) {
311 : const std::string reason = Adx::StrUtils::Format(
312 3 : Adx::ADUMP_REASON_EXCEPTION_DUMP_NOT_ENABLED, Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH);
313 45 : REPORT_EP0008_API_CALL_SEQUENCE(Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, reason);
314 3 : return ACL_ERROR_FAILURE;
315 3 : }
316 :
317 9 : std::string dumpPath;
318 9 : int32_t ret = Adx::DumpManager::Instance().GetExceptionDumpPath(dumpPath);
319 9 : if (ret != 0 || dumpPath.empty()) {
320 3 : IDE_LOGE("Get the exception dump path failed, path size=%zu, maxLen=%zu.", dumpPath.size(), maxLen);
321 3 : return ACL_ERROR_FAILURE;
322 : }
323 :
324 6 : if (dumpPath.size() + 1 > maxLen) {
325 : std::string reason = Adx::StrUtils::Format(Adx::ADUMP_REASON_BUFFER_SIZE_NOT_ENOUGH,
326 3 : std::to_string(maxLen).c_str(), std::to_string(dumpPath.size() + 1).c_str());
327 69 : REPORT_EP0006_INVALID_ARGUMENT(Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, std::to_string(maxLen),
328 : Adx::FUNC_ACL_DUMP_GET_EXCEPTION_INFO_PATH_PARAM_MAXLEN, reason);
329 3 : return ACL_ERROR_INVALID_PARAM;
330 3 : }
331 3 : if (strcpy_s(path, maxLen, dumpPath.c_str()) != EOK) {
332 0 : IDE_LOGE("Copy the path to buffer failed when get the exception dump path, path size=%zu, maxLen=%zu.",
333 : dumpPath.size(), maxLen);
334 0 : return ACL_ERROR_FAILURE;
335 : }
336 3 : return ACL_SUCCESS;
337 33 : }
|