* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <string.h>
#include "securec.h"
#include "dump_config.h"
#include "parse_dbg_file.h"
#include "tlv_parse.h"
#include "parse_json_file.h"
#include "dump_thread_manager.h"
#include "runtime/rt_model.h"
#include "runtime/mem.h"
#include "framework/executor_c/ge_log.h"
#include "ge/ge_error_codes.h"
#include "dump.h"
const char *DBG_FILE_SUFFIX = ".dbg";
Status DbgDumpInit(const char *cfg) {
Status ret = DumpConfigInit(cfg);
if (ret != SUCCESS) {
FreeDumpConfigRes();
GELOGI("Dump config file unavailable, result = %u", ret);
return SUCCESS;
}
if (GetDumpEnableFlag()) {
ret = InitDumpThread();
if (ret != SUCCESS) {
FreeDumpConfigRes();
return ret;
}
}
GELOGI("dbg dump init success");
return SUCCESS;
}
void *DbgCreateModelHandle(void) {
if (!GetDumpEnableFlag()) {
return NULL;
}
ModelDbgHandle *dbgHandle = (ModelDbgHandle *)mmMalloc(sizeof(ModelDbgHandle));
if (dbgHandle == NULL) {
return NULL;
}
memset_s(dbgHandle, sizeof(ModelDbgHandle), 0, sizeof(ModelDbgHandle));
return (void *)dbgHandle;
}
static void DbgFreeResource(ModelDbgHandle *modelDbgHandle) {
if (modelDbgHandle->aicpuDumpInfo != NULL) {
(void)mmFree(modelDbgHandle->aicpuDumpInfo);
modelDbgHandle->aicpuDumpInfo = NULL;
modelDbgHandle->aicpuDumpInfoLen = 0UL;
}
if (modelDbgHandle->dumpFileContent != NULL) {
mmFree(modelDbgHandle->dumpFileContent);
modelDbgHandle->dumpFileContent = NULL;
modelDbgHandle->dumpFileLen = 0UL;
modelDbgHandle->offset = 0UL;
}
if (modelDbgHandle->modelName != NULL) {
mmFree(modelDbgHandle->modelName);
modelDbgHandle->modelName = NULL;
}
mmFree(modelDbgHandle);
}
Status DbgDumpPreProcess(rtMdlLoad_t *mdlLoad, size_t taskDescSize, char *modelName, void *dbgHandle) {
if (!GetDumpEnableFlag()) {
return SUCCESS;
}
if ((dbgHandle == NULL) || (modelName == NULL)) {
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
ModelDbgHandle *modelDbgHandle = (ModelDbgHandle *)dbgHandle;
modelDbgHandle->taskDescBaseAddr = mdlLoad->taskDescBaseAddr;
modelDbgHandle->totalTaskNum = mdlLoad->totalTaskNum;
modelDbgHandle->taskDescSize = taskDescSize;
char *dumpPath = GetDumpPath();
uint32_t pathLen = strlen(dumpPath);
if (dumpPath[pathLen - 1] != '/') {
pathLen += 1;
}
uint32_t nameLen = strlen(modelName);
uint32_t suffixLen = strlen(DBG_FILE_SUFFIX);
uint32_t totalLen = pathLen + nameLen + suffixLen + 1;
char *dbgFileName = (char *)mmMalloc(totalLen);
if (dbgFileName == NULL) {
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
dbgFileName[pathLen - 1] = '/';
errno_t pathRet = memcpy_s(dbgFileName, totalLen, dumpPath, pathLen - 1);
errno_t nameRet = memcpy_s(dbgFileName + pathLen, totalLen - pathLen, modelName, nameLen);
errno_t suffixRet = strcpy_s(dbgFileName + pathLen + nameLen, totalLen - pathLen - nameLen, DBG_FILE_SUFFIX);
bool result = ((pathRet != EOK) || (nameRet != EOK) || (suffixRet != EOK));
if (result) {
mmFree(dbgFileName);
return ACL_ERROR_GE_MEMORY_OPERATE_FAILED;
}
uint8_t *dumpFileContent = ParseDbgFile(dbgFileName, modelDbgHandle);
mmFree(dbgFileName);
dbgFileName = NULL;
if (dumpFileContent == NULL) {
return ACL_ERROR_GE_INTERNAL_ERROR;
}
Status ret = ParseDbgHead(modelDbgHandle);
if (ret != SUCCESS) {
return ret;
}
uint32_t dumpStatus = GetDumpStatus();
if (dumpStatus == DUMP_NORMAL_ENABLE) {
ret = ParseDbgTlv(modelDbgHandle);
}
if (dumpStatus == DUMP_DEBUG_ENABLE) {
mdlLoad->overflow_en = 1;
}
return ret;
}
Status DbgDumpPostProcess(uint32_t modelId, uint64_t *stepIdAddr, void *dbgHandle) {
if (!GetDumpEnableFlag()) {
return SUCCESS;
}
if (dbgHandle == NULL) {
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
ModelDbgHandle *modelDbgHandle = (ModelDbgHandle *)dbgHandle;
modelDbgHandle->modelId = modelId;
modelDbgHandle->stepIdAddr = stepIdAddr;
uint32_t dumpStatus = GetDumpStatus();
if (dumpStatus == DUMP_NORMAL_ENABLE) {
if (modelDbgHandle->cfgMatchedCount == 0) {
GELOGI("modelName or opName is not matched .the load dump info not need to be sent.");
return SUCCESS;
}
}
Status ret = SendLoadInfoToAicpu(modelDbgHandle);
if (ret != SUCCESS) {
return ret;
}
modelDbgHandle->isSendFlag = true;
return SUCCESS;
}
void DbgStepIdCounterPlus(void *dbgHandle) {
if (!GetDumpEnableFlag()) {
return;
}
if (dbgHandle == NULL) {
return;
}
ModelDbgHandle *modelDbgHandle = (ModelDbgHandle *)dbgHandle;
if (!modelDbgHandle->isSendFlag) {
GELOGI("not sent dump info, stepId not need plus plus.");
return;
}
(*modelDbgHandle->stepIdAddr)++;
return;
}
void DbgFreeLoadDumpInfo(void *dbgHandle) {
if (!GetDumpEnableFlag()) {
return;
}
if (dbgHandle == NULL) {
return;
}
ModelDbgHandle *modelDbgHandle = (ModelDbgHandle *)dbgHandle;
if (modelDbgHandle->isSendFlag) {
(void)SendUnLoadInfoToAicpu(modelDbgHandle);
}
DbgFreeResource(modelDbgHandle);
return;
}
Status DbgDumpDeInit(void) {
if (!GetDumpEnableFlag()) {
return SUCCESS;
}
SetDumpEnableFlag(false);
rtError_t rtRet = rtDumpDeInit();
StopDumpThread();
DeInitDumpThread();
FreeDumpConfigRes();
GELOGI("dbg dump deinit success");
return (Status)rtRet;
}