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 594 : REPORT_EP0006_INVALID_ARGUMENT(
51 : FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, param, 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(
58 : index, field,
59 36 : StrUtils::Format(ADUMP_REASON_PARAM_VALUE_NOT_SUPPORTED, std::to_string(value).c_str(), expected));
60 : }
61 :
62 57 : bool CheckAclDumpTensorShape(const acldumpTensorInfo& src, size_t index)
63 : {
64 57 : const std::string maxShapeNum = std::to_string(ACL_DUMP_MAX_SHAPE_NUM);
65 57 : if (src.shapeNum > ACL_DUMP_MAX_SHAPE_NUM) {
66 3 : return ReportInvalidTensorField(
67 : index, "shapeNum",
68 9 : StrUtils::Format(
69 9 : ADUMP_REASON_PARAM_VALUE_EXCEED_LIMIT, std::to_string(src.shapeNum).c_str(), maxShapeNum.c_str()));
70 : }
71 54 : if (src.originShapeNum > ACL_DUMP_MAX_SHAPE_NUM) {
72 3 : return ReportInvalidTensorField(
73 : index, "originShapeNum",
74 9 : StrUtils::Format(
75 6 : ADUMP_REASON_PARAM_VALUE_EXCEED_LIMIT, std::to_string(src.originShapeNum).c_str(),
76 3 : maxShapeNum.c_str()));
77 : }
78 51 : return true;
79 57 : }
80 :
81 51 : bool CheckAclDumpTensorEnum(const acldumpTensorInfo& src, size_t index)
82 : {
83 51 : if (src.type != ACL_DUMP_TENSOR_INPUT && src.type != ACL_DUMP_TENSOR_OUTPUT &&
84 6 : src.type != ACL_DUMP_TENSOR_WORKSPACE) {
85 6 : return ReportUnsupportedTensorField(
86 3 : index, "type", static_cast<int32_t>(src.type),
87 3 : "ACL_DUMP_TENSOR_INPUT/ACL_DUMP_TENSOR_OUTPUT/ACL_DUMP_TENSOR_WORKSPACE");
88 : }
89 48 : if (src.addrType != ACL_DUMP_ADDR_RAW) {
90 9 : return ReportUnsupportedTensorField(index, "addrType", static_cast<int32_t>(src.addrType), "ACL_DUMP_ADDR_RAW");
91 : }
92 39 : if (src.placement != ACL_DUMP_PLACEMENT_DEVICE) {
93 12 : return ReportUnsupportedTensorField(
94 6 : index, "placement", static_cast<int32_t>(src.placement), "ACL_DUMP_PLACEMENT_DEVICE");
95 : }
96 33 : return true;
97 : }
98 :
99 33 : bool CheckAclDumpTensorData(const acldumpTensorInfo& src, size_t index)
100 : {
101 33 : if (src.tensorAddr == nullptr) {
102 6 : std::string param = StrUtils::Format("tensors[%zu].tensorAddr", index);
103 84 : REPORT_EP0007_NULL_POINTER(FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, param);
104 6 : return false;
105 6 : }
106 27 : if (src.tensorSize == 0) {
107 3 : return ReportInvalidTensorField(
108 6 : index, "tensorSize", StrUtils::Format(ADUMP_REASON_PARAM_MUST_BE_GREATER_THAN, "0"));
109 : }
110 24 : return true;
111 12 : }
112 :
113 57 : bool ConvertAclDumpTensor(const acldumpTensorInfo& src, size_t index, TensorInfo& dst)
114 : {
115 90 : if (!CheckAclDumpTensorShape(src, index) || !CheckAclDumpTensorEnum(src, index) ||
116 33 : !CheckAclDumpTensorData(src, index)) {
117 33 : return false;
118 : }
119 :
120 24 : ConvertAclDumpTensorInner(src, index, dst);
121 24 : return true;
122 : }
123 : } // namespace
124 :
125 45022 : void* AdumpGetSizeInfoAddr(uint32_t space, uint32_t& atomicIndex)
126 : {
127 45022 : if (!g_setAssert) {
128 3 : const std::lock_guard<std::mutex> lock(g_setAssertMtx);
129 3 : if (!g_setAssert) {
130 3 : (void)rtSetTaskFailCallback(AdxAssertCallBack);
131 3 : g_setAssert = true;
132 : }
133 3 : }
134 45022 : if (space > MAX_TENSOR_NUM) {
135 3 : return nullptr;
136 : }
137 :
138 45019 : atomicIndex = g_atomicIndex++;
139 45019 : auto nextWriteCursor = g_writeIdx.fetch_add(space);
140 45019 : return g_chunk + (nextWriteCursor % RING_CHUNK_SIZE);
141 : }
142 :
143 18 : int32_t AdumpRegisterCallback(uint32_t moduleId, AdumpCallback enableFunc, AdumpCallback disableFunc)
144 : {
145 18 : return DumpManager::Instance().RegisterCallback(moduleId, enableFunc, disableFunc);
146 : }
147 :
148 24 : int32_t AdumpSaveToFile(const char* data, size_t dataLen, const char* filename, SaveType type)
149 : {
150 24 : return DumpManager::Instance().SaveFile(data, dataLen, filename, type);
151 : }
152 : } // namespace Adx
153 :
154 : /**
155 : * @ingroup AscendCL
156 : * @brief Enable the dump function of the corresponding dump type.
157 : *
158 : * @param dumpType [IN] type of dump
159 : * @param path [IN] dump path
160 : *
161 : * @retval ACL_SUCCESS The function is successfully executed.
162 : * @retval OtherValues Failure
163 : */
164 30 : aclError aclopStartDumpArgs(uint32_t dumpType, const char* path)
165 : {
166 30 : if (path == nullptr) {
167 48 : REPORT_EP0007_NULL_POINTER(Adx::FUNC_NAME_ACL_OP_START_DUMP_ARGS, Adx::FUNC_ACL_OP_START_DUMP_ARGS_PARAM_PATH);
168 3 : return ACL_ERROR_FAILURE;
169 : }
170 :
171 27 : if ((dumpType & ACL_OP_DUMP_OP_AICORE_ARGS) != ACL_OP_DUMP_OP_AICORE_ARGS) {
172 6 : std::string dumpTypeStr = std::to_string(dumpType);
173 6 : std::string expTypeStr = std::to_string(ACL_OP_DUMP_OP_AICORE_ARGS);
174 6 : std::string reason = Adx::StrUtils::Format(Adx::ADUMP_REASON_RESERVED_PARAM_MUST_EQUAL, expTypeStr.c_str());
175 132 : REPORT_EP0006_INVALID_ARGUMENT(
176 : Adx::FUNC_NAME_ACL_OP_START_DUMP_ARGS, dumpTypeStr, Adx::FUNC_ACL_OP_START_DUMP_ARGS_PARAM_DUMPTYPE,
177 : 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(
238 : const char* fileName, const char* userTag, const acldumpTensorInfo* tensors, size_t tensorCount)
239 : {
240 66 : if (fileName == nullptr) {
241 48 : 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 75 : REPORT_EP0006_INVALID_ARGUMENT(
248 : Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, "", Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_FILENAME,
249 : Adx::ADUMP_REASON_PARAM_PATH_EMPTY);
250 3 : return ACL_ERROR_INVALID_PARAM;
251 : }
252 :
253 120 : if (Adx::Path::HasParentDirSegment(fileName)) {
254 150 : REPORT_EP0006_INVALID_ARGUMENT(
255 : Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, fileName,
256 : Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_FILENAME, Adx::ADUMP_REASON_PARAM_PATH_HAS_PARENT_DIR);
257 6 : return ACL_ERROR_INVALID_PARAM;
258 : }
259 :
260 54 : if (tensors == nullptr) {
261 48 : REPORT_EP0007_NULL_POINTER(
262 : Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_TENSORS);
263 3 : return ACL_ERROR_INVALID_PARAM;
264 : }
265 :
266 51 : if (tensorCount == 0) {
267 3 : const std::string reason = Adx::StrUtils::Format(Adx::ADUMP_REASON_PARAM_MUST_BE_GREATER_THAN, "0");
268 66 : REPORT_EP0006_INVALID_ARGUMENT(
269 : Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, std::to_string(tensorCount),
270 : Adx::FUNC_ACL_DUMP_SAVE_EXCEPTION_INFO_PARAM_TENSORCOUNT, reason);
271 3 : return ACL_ERROR_INVALID_PARAM;
272 3 : }
273 :
274 48 : if (!Adx::DumpManager::Instance().IsEnabledExceptionDump()) {
275 : const std::string reason = Adx::StrUtils::Format(
276 0 : Adx::ADUMP_REASON_EXCEPTION_DUMP_NOT_ENABLED, Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO);
277 0 : REPORT_EP0008_API_CALL_SEQUENCE(Adx::FUNC_NAME_ACL_DUMP_SAVE_EXCEPTION_INFO, reason);
278 0 : return ACL_ERROR_FAILURE;
279 0 : }
280 :
281 48 : std::vector<Adx::TensorInfo> tensorInfos(tensorCount);
282 72 : for (size_t i = 0; i < tensorCount; ++i) {
283 57 : if (!Adx::ConvertAclDumpTensor(tensors[i], i, tensorInfos[i])) {
284 33 : return ACL_ERROR_INVALID_PARAM;
285 : }
286 : }
287 :
288 15 : const std::string userTagStr = (userTag == nullptr) ? "" : userTag;
289 30 : const int32_t ret = Adx::DumpManager::Instance().SaveExceptionInfo(fileName, userTagStr, tensorInfos);
290 15 : return ret == 0 ? ACL_SUCCESS : ACL_ERROR_FAILURE;
291 72 : }
292 :
293 : /**
294 : * @ingroup AscendCL
295 : * @brief Get the Exception Dump root path({dump_path}/extra-info/data-dump/{deviceId}/).
296 : * @retval ACL_SUCCESS The function is successfully executed.
297 : * @retval OtherValues Failure
298 : */
299 21 : aclError acldumpGetExceptionInfoPath(char* path, size_t maxLen)
300 : {
301 21 : if (path == nullptr) {
302 48 : REPORT_EP0007_NULL_POINTER(
303 : Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, Adx::FUNC_ACL_DUMP_GET_EXCEPTION_INFO_PATH_PARAM_PATH);
304 3 : return ACL_ERROR_INVALID_PARAM;
305 : }
306 18 : if (maxLen <= 1) {
307 6 : std::string reason = Adx::StrUtils::Format(Adx::ADUMP_REASON_PARAM_MUST_BE_GREATER_THAN, "1");
308 132 : REPORT_EP0006_INVALID_ARGUMENT(
309 : Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, std::to_string(maxLen),
310 : Adx::FUNC_ACL_DUMP_GET_EXCEPTION_INFO_PATH_PARAM_MAXLEN, reason);
311 6 : return ACL_ERROR_INVALID_PARAM;
312 6 : }
313 :
314 12 : if (!Adx::DumpManager::Instance().IsEnabledExceptionDump()) {
315 : const std::string reason = Adx::StrUtils::Format(
316 3 : Adx::ADUMP_REASON_EXCEPTION_DUMP_NOT_ENABLED, Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH);
317 42 : REPORT_EP0008_API_CALL_SEQUENCE(Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, reason);
318 3 : return ACL_ERROR_FAILURE;
319 3 : }
320 :
321 9 : std::string dumpPath;
322 9 : int32_t ret = Adx::DumpManager::Instance().GetExceptionDumpPath(dumpPath);
323 9 : if (ret != 0 || dumpPath.empty()) {
324 3 : IDE_LOGE("Get the exception dump path failed, path size=%zu, maxLen=%zu.", dumpPath.size(), maxLen);
325 3 : return ACL_ERROR_FAILURE;
326 : }
327 :
328 6 : if (dumpPath.size() + 1 > maxLen) {
329 : std::string reason = Adx::StrUtils::Format(
330 6 : Adx::ADUMP_REASON_BUFFER_SIZE_NOT_ENOUGH, std::to_string(maxLen).c_str(),
331 9 : std::to_string(dumpPath.size() + 1).c_str());
332 66 : REPORT_EP0006_INVALID_ARGUMENT(
333 : Adx::FUNC_NAME_ACL_DUMP_GET_EXCEPTION_INFO_PATH, std::to_string(maxLen),
334 : Adx::FUNC_ACL_DUMP_GET_EXCEPTION_INFO_PATH_PARAM_MAXLEN, reason);
335 3 : return ACL_ERROR_INVALID_PARAM;
336 3 : }
337 3 : if (strcpy_s(path, maxLen, dumpPath.c_str()) != EOK) {
338 0 : IDE_LOGE(
339 : "Copy the path to buffer failed when get the exception dump path, path size=%zu, maxLen=%zu.",
340 : dumpPath.size(), maxLen);
341 0 : return ACL_ERROR_FAILURE;
342 : }
343 3 : return ACL_SUCCESS;
344 33 : }
|