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 "stacktrace_safe_recorder.h"
12 : #include <errno.h>
13 : #include "securec.h"
14 : #include "stacktrace_logger.h"
15 : #include "stacktrace_file_struct.h"
16 : #include "trace_recorder.h"
17 : #include "trace_system_api.h"
18 : #include "trace_types.h"
19 : #include "adiag_utils.h"
20 : #include "adiag_print.h"
21 :
22 : #define PROCESS_SECTION "[process]\n"
23 : #define STACK_SECTION "[stack]\n"
24 : #define MAPS_SECTION "[maps]\n"
25 : #define MEMORY_SECTION "[system memory]\n"
26 : #define STATUS_SECTION "[process status]\n"
27 : #define LIMITS_SECTION "[process limits]\n"
28 :
29 : #define PROC_MEMINFO_PATH "/proc/meminfo"
30 :
31 : STATIC TraceStackInfo g_stackInfo = { 0 };
32 : STATIC struct StackcoreBuffer g_stackBuff = { 0 };
33 :
34 : /**
35 : * @brief read a line data from file
36 : * @param [in] fd: file descriptor
37 : * @param [in] data: write data
38 : * @param [in] len: data buffer length
39 : * @return >0 success; -1 failed
40 : */
41 39571 : ssize_t TraceSafeReadLine(int32_t fd, char *data, uint32_t len)
42 : {
43 39571 : if (fd < 0 || data == NULL || len == 0) {
44 20 : return -1;
45 : }
46 :
47 39551 : ssize_t n = 1;
48 39551 : char c = (char)EOF;
49 39551 : char *ptr = data;
50 3045930 : while (n < (ssize_t)len) {
51 3045815 : ssize_t rc = read(fd, &c, 1);
52 3045815 : if (rc == 1) {
53 3045204 : *ptr = c;
54 3045204 : ptr++;
55 3045204 : if (c == '\n') {
56 38845 : break;
57 : }
58 611 : } else if (rc == 0) {
59 571 : *ptr = '\0';
60 571 : return (n - 1);
61 : } else {
62 40 : if (errno == EINTR) {
63 20 : continue;
64 : }
65 20 : return -1;
66 : }
67 3006359 : n++;
68 : }
69 38960 : *ptr = '\0';
70 38960 : return n;
71 : }
72 :
73 : /**
74 : * @brief safe write data to file
75 : * @param [in] fd: file descriptor
76 : * @param [in] data: write data
77 : * @param [in] len: data buffer length
78 : * @return TraStatus
79 : */
80 29339 : STATIC TraStatus TraceSafeWrite(int32_t fd, const char *data, size_t len)
81 : {
82 29339 : if ((fd < 0) || (data == NULL) || (len == 0)) {
83 80 : return TRACE_INVALID_PARAM;
84 : }
85 :
86 29259 : size_t reserved = len;
87 : do {
88 29279 : ssize_t wrLen = write(fd, data + (len - reserved), reserved);
89 29279 : if (wrLen < 0 && errno == EINTR) {
90 20 : wrLen = 0;
91 29259 : } else if (wrLen < 0) {
92 40 : return TRACE_FAILURE;
93 : } else {
94 : ;
95 : }
96 29239 : reserved -= (size_t)wrLen;
97 29239 : } while (reserved != 0);
98 29219 : return TRACE_SUCCESS;
99 : }
100 :
101 0 : const char* TraceSafeGetFilePath(void)
102 : {
103 0 : return TraceRecorderSafeGetFilePath();
104 : }
105 :
106 : /**
107 : * @brief get fd to write stackcore file
108 : use for signal_callback_func, only call reentrant function
109 : * @param [in] info: info, for dir name and file name
110 : * @param [in] suffix: file suffix
111 : * @param [out] fd: file handle
112 : * @return TraStatus
113 : */
114 215 : TraStatus TraceSafeGetFd(const TraceStackRecorderInfo *info, const char *suffix, int32_t *fd)
115 : {
116 215 : if ((info == NULL) || (fd == NULL)) {
117 20 : return TRACE_INVALID_PARAM;
118 : }
119 :
120 195 : char timeString[TIMESTAMP_MAX_LENGTH] = { 0 };
121 195 : uint64_t fileTime = GetRealTime();
122 195 : TraStatus ret = TimestampToFileStr(fileTime, timeString, TIMESTAMP_MAX_LENGTH);
123 195 : if (ret != TRACE_SUCCESS) {
124 20 : return ret;
125 : }
126 175 : char objName[MAX_FILEPATH_LEN] = { 0 };
127 175 : int32_t err = snprintf_s(objName, MAX_FILEPATH_LEN, MAX_FILEPATH_LEN - 1U,
128 175 : "%d_%d_%s_%s", info->signo, info->tid, program_invocation_short_name, timeString);
129 175 : if (err == -1) {
130 0 : return TRACE_FAILURE;
131 : }
132 :
133 : // get dir time by crash time
134 175 : ret = TimestampToFileStr(info->crashTime, timeString, TIMESTAMP_MAX_LENGTH);
135 175 : if (ret != TRACE_SUCCESS) {
136 20 : return ret;
137 : }
138 :
139 155 : g_stackBuff.head.magic = STACK_HEAD_MAGIC;
140 155 : g_stackBuff.head.version = STACK_HEAD_VERSION;
141 155 : TraceDirInfo dirInfo = { TRACER_STACKCORE_NAME, info->pid, timeString, false };
142 155 : TraceFileInfo fileInfo = { TRACER_STACKCORE_NAME, objName, suffix };
143 155 : return TraceRecorderSafeGetFd(&dirInfo, &fileInfo, fd);
144 : }
145 :
146 195 : TraceStackInfo *TraceSafeGetStackBuffer(void)
147 : {
148 195 : return &g_stackInfo;
149 : }
150 :
151 : /**
152 : * @brief write "system memory" info
153 : * @param [in] fd: handle of stack core file
154 : * @return TraStatus
155 : */
156 255 : STATIC TraStatus TraceSafeWriteMemoryInfo(int32_t fd)
157 : {
158 : // write title [system memory]
159 255 : TraStatus ret = TraceSafeWrite(fd, MEMORY_SECTION, strlen(MEMORY_SECTION));
160 255 : if (ret != TRACE_SUCCESS) {
161 40 : LOGE("write memory title failed, ret=%d, errno=%d", ret, errno);
162 40 : return ret;
163 : }
164 :
165 : // write memory info
166 215 : int32_t memFd = open(PROC_MEMINFO_PATH, O_RDONLY);
167 215 : if (memFd < 0) {
168 20 : LOGE("memory info file open failed, errno=%d", errno);
169 20 : return TRACE_FAILURE;
170 : }
171 :
172 195 : char info[CORE_BUFFER_LEN] = { 0 };
173 9120 : while (TraceSafeReadLine(memFd, info, CORE_BUFFER_LEN) > 0) {
174 8945 : ret = TraceSafeWrite(fd, info, strlen(info));
175 8945 : if (ret != TRACE_SUCCESS) {
176 20 : LOGE("write memory info to file failed, ret=%d, errno=%d", ret, errno);
177 20 : TraceClose(&memFd);
178 20 : return ret;
179 : }
180 : }
181 175 : TraceClose(&memFd);
182 175 : (void)TraceSafeWrite(fd, "\n", 1);
183 175 : return TRACE_SUCCESS;
184 : }
185 :
186 : /**
187 : * @brief write "process status" info
188 : * @param [in] fd: handle of stack core file
189 : * @param [in] pid: process id
190 : * @return TraStatus
191 : */
192 275 : STATIC TraStatus TraceSafeWriteStatusInfo(int32_t fd, int32_t pid)
193 : {
194 : // write title [process status]
195 275 : TraStatus ret = TraceSafeWrite(fd, STATUS_SECTION, strlen(STATUS_SECTION));
196 275 : if (ret != TRACE_SUCCESS) {
197 40 : LOGE("write status title failed, ret=%d, errno=%d", ret, errno);
198 40 : return ret;
199 : }
200 235 : char path[CORE_BUFFER_LEN] = { 0 };
201 235 : int32_t err = snprintf_s(path, CORE_BUFFER_LEN, CORE_BUFFER_LEN - 1U, "/proc/%d/status", pid);
202 235 : if (err == -1) {
203 20 : LOGE("snprintf_s status path failed");
204 20 : return TRACE_FAILURE;
205 : }
206 : // write status info
207 215 : int32_t statFd = open(path, O_RDONLY);
208 215 : if (statFd < 0) {
209 80 : LOGE("status file open failed, errno=%d", errno);
210 80 : return TRACE_FAILURE;
211 : }
212 :
213 135 : char info[CORE_BUFFER_LEN] = { 0 };
214 6690 : while (TraceSafeReadLine(statFd, info, CORE_BUFFER_LEN) > 0) {
215 6575 : ret = TraceSafeWrite(fd, info, strlen(info));
216 6575 : if (ret != TRACE_SUCCESS) {
217 20 : LOGE("write status info to file failed, ret=%d, errno=%d", ret, errno);
218 20 : TraceClose(&statFd);
219 20 : return ret;
220 : }
221 : }
222 115 : TraceClose(&statFd);
223 115 : (void)TraceSafeWrite(fd, "\n", 1);
224 115 : return TRACE_SUCCESS;
225 : }
226 :
227 :
228 : /**
229 : * @brief write "process limits" info
230 : * @param [in] fd: handle of stack core file
231 : * @param [in] pid: process id
232 : * @return TraStatus
233 : */
234 275 : STATIC TraStatus TraceSafeWriteLimitsInfo(int32_t fd, int32_t pid)
235 : {
236 : // write title [process limits]
237 275 : TraStatus ret = TraceSafeWrite(fd, LIMITS_SECTION, strlen(LIMITS_SECTION));
238 275 : if (ret != TRACE_SUCCESS) {
239 40 : LOGE("write limits title failed, ret=%d, errno=%d", ret, errno);
240 40 : return ret;
241 : }
242 235 : char path[CORE_BUFFER_LEN] = { 0 };
243 235 : int32_t err = snprintf_s(path, CORE_BUFFER_LEN, CORE_BUFFER_LEN - 1U, "/proc/%d/limits", pid);
244 235 : if (err == -1) {
245 20 : LOGE("snprintf_s limits path failed");
246 20 : return TRACE_FAILURE;
247 : }
248 : // write limits info
249 215 : int32_t limitsFd = open(path, O_RDONLY);
250 215 : if (limitsFd < 0) {
251 80 : LOGE("limits file open failed, errno=%d", errno);
252 80 : return TRACE_FAILURE;
253 : }
254 :
255 135 : char info[CORE_BUFFER_LEN] = { 0 };
256 2090 : while (TraceSafeReadLine(limitsFd, info, CORE_BUFFER_LEN) > 0) {
257 1975 : ret = TraceSafeWrite(fd, info, strlen(info));
258 1975 : if (ret != TRACE_SUCCESS) {
259 20 : LOGE("write limits info to file failed, ret=%d, errno=%d", ret, errno);
260 20 : TraceClose(&limitsFd);
261 20 : return ret;
262 : }
263 : }
264 115 : TraceClose(&limitsFd);
265 115 : (void)TraceSafeWrite(fd, "\n", 1);
266 115 : return TRACE_SUCCESS;
267 : }
268 :
269 : /**
270 : * @brief write "maps" info
271 : * @param [in] fd: handle of stack core file
272 : * @param [in] pid: process id
273 : * @return TraStatus
274 : */
275 275 : STATIC TraStatus TraceSafeWriteMapsInfo(int32_t fd, int32_t pid)
276 : {
277 : // write title [maps]
278 275 : TraStatus ret = TraceSafeWrite(fd, MAPS_SECTION, strlen(MAPS_SECTION));
279 275 : if (ret != TRACE_SUCCESS) {
280 40 : LOGE("write maps title failed, ret=%d, errno=%d", ret, errno);
281 40 : return ret;
282 : }
283 :
284 235 : char path[CORE_BUFFER_LEN] = { 0 };
285 235 : int32_t err = snprintf_s(path, CORE_BUFFER_LEN, CORE_BUFFER_LEN - 1U, "/proc/%d/maps", pid);
286 235 : if (err == -1) {
287 20 : LOGE("snprintf_s maps path failed");
288 20 : return TRACE_FAILURE;
289 : }
290 : // write maps info
291 215 : int32_t mapFd = open(path, O_RDONLY);
292 215 : if (mapFd < 0) {
293 80 : LOGE("self map open failed, errno=%d", errno);
294 80 : return TRACE_FAILURE;
295 : }
296 :
297 135 : char info[CORE_BUFFER_LEN] = { 0 };
298 9274 : while (TraceSafeReadLine(mapFd, info, CORE_BUFFER_LEN) > 0) {
299 9179 : ret = TraceSafeWrite(fd, info, strlen(info));
300 9179 : if (ret != TRACE_SUCCESS) {
301 40 : LOGE("write maps info to file failed, ret=%d, errno=%d", ret, errno);
302 40 : TraceClose(&mapFd);
303 40 : return ret;
304 : }
305 : }
306 95 : TraceClose(&mapFd);
307 95 : (void)TraceSafeWrite(fd, "\n", 1);
308 95 : return TRACE_SUCCESS;
309 : }
310 :
311 : /**
312 : * @brief write "system memory" info
313 : * @param [in] fd: handle of stack core file
314 : * @param [in] pid: process id
315 : * @return TraStatus
316 : */
317 215 : TraStatus TraceSafeWriteSystemInfo(int32_t fd, int32_t pid)
318 : {
319 215 : TraStatus ret = TraceSafeWriteMapsInfo(fd, pid);
320 215 : if (ret != TRACE_SUCCESS) {
321 120 : LOGW("can not write maps info to file, ret=%d.", ret);
322 : }
323 :
324 215 : ret = TraceSafeWriteMemoryInfo(fd);
325 215 : if (ret != TRACE_SUCCESS) {
326 40 : LOGW("can not write memory info to file, ret=%d.", ret);
327 : }
328 :
329 215 : ret = TraceSafeWriteStatusInfo(fd, pid);
330 215 : if (ret != TRACE_SUCCESS) {
331 100 : LOGW("can not write process info to file, ret=%d.", ret);
332 : }
333 :
334 215 : ret = TraceSafeWriteLimitsInfo(fd, pid);
335 215 : if (ret != TRACE_SUCCESS) {
336 100 : LOGW("can not write limits info to file, ret=%d.", ret);
337 : }
338 :
339 215 : return TRACE_SUCCESS;
340 : }
341 :
342 : /**
343 : * @brief write "stack" info
344 : * @param [in] fd: handle of stack core file
345 : * @param [in] info: stack info
346 : * @return TraStatus
347 : */
348 275 : TraStatus TraceSafeWriteStackInfo(int32_t fd, const TraceStackInfo *info)
349 : {
350 275 : if (info == NULL) {
351 20 : return TRACE_INVALID_PARAM;
352 : }
353 :
354 : // write title [stack]
355 255 : TraStatus ret = TRACE_FAILURE;
356 255 : if (info->threadIdx == 0) {
357 255 : ret = TraceSafeWrite(fd, STACK_SECTION, strlen(STACK_SECTION));
358 255 : if (ret != TRACE_SUCCESS) {
359 20 : LOGE("write stack title failed, errno=%d", errno);
360 20 : return ret;
361 : }
362 : }
363 :
364 : // write stack info
365 235 : char buf[CORE_BUFFER_LEN] = { 0 };
366 235 : (void)snprintf_s(buf, CORE_BUFFER_LEN, CORE_BUFFER_LEN - 1U, "Thread %u (%d, %s)\n",
367 235 : info->threadIdx + 1U, info->threadTid, info->threadName);
368 235 : (void)TraceSafeWrite(fd, buf, strlen(buf));
369 :
370 235 : int32_t layer = info->layer;
371 235 : if (layer < 0) {
372 60 : (void)TraceSafeWrite(fd, info->errLog, strlen(info->errLog));
373 60 : (void)TraceSafeWrite(fd, "\n", 1);
374 60 : return TRACE_FAILURE;
375 : }
376 175 : if (layer >= MAX_STACK_LAYER) {
377 20 : LOGE("layer %d exceed the upper limit: %d", layer, MAX_STACK_LAYER);
378 20 : return TRACE_FAILURE;
379 : }
380 485 : for (int32_t i = 0; i <= layer; i++) {
381 350 : ret = TraceSafeWrite(fd, info->frame[i].info, strlen(info->frame[i].info));
382 350 : if (ret != TRACE_SUCCESS) {
383 20 : LOGE("write stack layer %d failed, ret=%d", i, ret);
384 20 : return ret;
385 : }
386 : }
387 135 : (void)TraceSafeWrite(fd, "\n", 1);
388 135 : return TRACE_SUCCESS;
389 : }
390 :
391 : /**
392 : * @brief write "process" info
393 : * @param [in] fd: handle of stack_core file
394 : * @param [in] info: process info
395 : * @return TraStatus
396 : */
397 215 : TraStatus TraceSafeWriteProcessInfo(int32_t fd, const TraceStackProcessInfo *info)
398 : {
399 215 : if (info == NULL) {
400 20 : return TRACE_INVALID_PARAM;
401 : }
402 : // write title [process]
403 195 : TraStatus ret = TraceSafeWrite(fd, PROCESS_SECTION, strlen(PROCESS_SECTION));
404 195 : if (ret != TRACE_SUCCESS) {
405 20 : LOGE("write process title failed, errno=%d", errno);
406 20 : return ret;
407 : }
408 :
409 : // write process info
410 175 : char data[CORE_BUFFER_LEN] = { 0 };
411 175 : int32_t err = snprintf_s(data, CORE_BUFFER_LEN, CORE_BUFFER_LEN - 1U,
412 : "crash reason:%d\ncrash pid:%d\ncrash tid:%d\ncrash stack base:0x%016lx\ncrash stack top:0x%016lx\n\n",
413 175 : info->signo, info->pid, info->tid, info->baseAddr, info->topAddr);
414 175 : if (err == -1) {
415 0 : LOGE("snprintf_s process info failed");
416 0 : return TRACE_FAILURE;
417 : }
418 175 : ret = TraceSafeWrite(fd, data, strlen(data));
419 175 : if (ret != TRACE_SUCCESS) {
420 20 : LOGE("write process info failed, info : %s", strerror(AdiagGetErrorCode()));
421 20 : return ret;
422 : }
423 155 : return TRACE_SUCCESS;
424 : }
425 :
426 20 : TraStatus TraceSaveProcessReg(uintptr_t *regs, uint32_t regSize)
427 : {
428 20 : errno_t err = memcpy_s(g_stackBuff.process.regs, sizeof(uintptr_t) * TRACE_CORE_REG_NUM, regs, regSize);
429 20 : if (err != EOK) {
430 20 : LOGE("memcpy failed, err = %d, errno = %d.", (int32_t)err, errno);
431 20 : return TRACE_FAILURE;
432 : }
433 0 : return TRACE_SUCCESS;
434 : }
435 :
436 0 : STATIC TraStatus TraceSaveProcessTask(int32_t pid)
437 : {
438 0 : char path[CORE_BUFFER_LEN] = { 0 };
439 0 : int32_t err = snprintf_s(path, CORE_BUFFER_LEN, CORE_BUFFER_LEN - 1U, "/proc/%d/cmdline", pid);
440 0 : if (err == -1) {
441 0 : LOGE("snprintf_s cmdline path failed");
442 0 : return TRACE_FAILURE;
443 : }
444 :
445 0 : int32_t cmdFd = open(path, O_RDONLY);
446 0 : if (cmdFd < 0) {
447 0 : LOGE("cmdline file open failed, errno=%d", errno);
448 0 : return TRACE_FAILURE;
449 : }
450 :
451 0 : if (TraceSafeReadLine(cmdFd, g_stackBuff.process.task, (uint32_t)sizeof(g_stackBuff.process.task)) <= 0) {
452 0 : LOGE("read task info failed, errno=%d", errno);
453 0 : TraceClose(&cmdFd);
454 0 : return TRACE_FAILURE;
455 : }
456 0 : TraceClose(&cmdFd);
457 0 : return TRACE_SUCCESS;
458 : }
459 :
460 : /**
461 : * @brief save process info
462 : * @param [in] info: stack info
463 : * @return TraStatus
464 : */
465 0 : TraStatus TraceSaveProcessInfo(const TraceStackProcessInfo *info)
466 : {
467 0 : g_stackBuff.process.pid = info->pid;
468 0 : g_stackBuff.process.crashTid = info->tid;
469 0 : g_stackBuff.process.signo = info->signo;
470 0 : g_stackBuff.process.crashTime = info->crashTime;
471 0 : g_stackBuff.process.baseAddr = info->baseAddr;
472 0 : g_stackBuff.process.topAddr = info->topAddr;
473 0 : return TraceSaveProcessTask(info->pid);
474 : }
475 :
476 : /**
477 : * @brief save stack info
478 : * @param [in] info: stack info
479 : * @return TraStatus
480 : */
481 120 : TraStatus TraceSaveStackInfo(const TraceStackInfo *info)
482 : {
483 120 : if (info == NULL) {
484 20 : return TRACE_INVALID_PARAM;
485 : }
486 100 : if (info->threadIdx >= MAX_THREAD_NUM) {
487 20 : return TRACE_INVALID_PARAM;
488 : }
489 :
490 80 : ScThreadInfo *thread = &g_stackBuff.thread[info->threadIdx];
491 80 : thread->tid = info->threadTid;
492 80 : thread->layer = info->layer;
493 80 : errno_t err = strncpy_s(thread->name, THREAD_NAME_LEN, info->threadName, strlen(info->threadName));
494 80 : if (err != EOK) {
495 20 : LOGE("strcpy thread name failed");
496 20 : return TRACE_FAILURE;
497 : }
498 :
499 60 : int32_t layer = info->layer;
500 60 : if (layer < 0) {
501 20 : return TRACE_FAILURE;
502 : }
503 40 : if (layer >= MAX_STACK_LAYER) {
504 20 : LOGE("layer %d exceed the upper limit: %d", layer, MAX_STACK_LAYER);
505 20 : return TRACE_FAILURE;
506 : }
507 :
508 20 : err = memcpy_s(thread->frames, sizeof(ScdFrames) * (size_t)MAX_STACK_LAYER,
509 20 : info->frame, sizeof(TraceFrameInfo) * (size_t)MAX_STACK_LAYER);
510 20 : if (err != EOK) {
511 20 : LOGE("memcpy thread frames failed");
512 20 : return TRACE_FAILURE;
513 : }
514 :
515 0 : return TRACE_SUCCESS;
516 : }
517 :
518 0 : TraStatus TraceSafeWriteBuff(int32_t fd)
519 : {
520 0 : TraStatus ret = TraceSafeWrite(fd, (const char *)&g_stackBuff, sizeof(g_stackBuff));
521 0 : (void)memset_s(&g_stackBuff, sizeof(struct StackcoreBuffer), 0, sizeof(struct StackcoreBuffer));
522 0 : if (ret != TRACE_SUCCESS) {
523 0 : LOGE("write buffer to file failed, info : %s", strerror(AdiagGetErrorCode()));
524 0 : return ret;
525 : }
526 0 : return TRACE_SUCCESS;
527 : }
528 :
529 151 : TraStatus TraceSafeMkdirPath(const TraceStackRecorderInfo *info)
530 : {
531 151 : if (info == NULL) {
532 20 : return TRACE_INVALID_PARAM;
533 : }
534 :
535 : // get dir time by crash time
536 131 : char timeString[TIMESTAMP_MAX_LENGTH] = { 0 };
537 131 : TraStatus ret = TimestampToFileStr(info->crashTime, timeString, TIMESTAMP_MAX_LENGTH);
538 131 : if (ret != TRACE_SUCCESS) {
539 20 : LOGE("get dir time failed, ret=%d", ret);
540 20 : return ret;
541 : }
542 :
543 111 : TraceDirInfo dirInfo = { TRACER_STACKCORE_NAME, info->pid, timeString, false };
544 111 : return TraceRecorderSafeMkdirPath(&dirInfo);
545 : }
546 :
547 260 : TraStatus TraceSafeGetDirPath(const TraceStackRecorderInfo *info, char *path, size_t len)
548 : {
549 260 : if ((info == NULL) || (path == NULL) || (len == 0)) {
550 60 : return TRACE_INVALID_PARAM;
551 : }
552 :
553 : // get dir time by crash time
554 200 : char timeString[TIMESTAMP_MAX_LENGTH] = { 0 };
555 200 : TraStatus ret = TimestampToFileStr(info->crashTime, timeString, TIMESTAMP_MAX_LENGTH);
556 200 : if (ret != TRACE_SUCCESS) {
557 20 : LOGE("get dir time failed, ret=%d", ret);
558 20 : return ret;
559 : }
560 :
561 180 : TraceDirInfo dirInfo = { TRACER_STACKCORE_NAME, info->pid, timeString, false };
562 180 : return TraceRecorderSafeGetDirPath(&dirInfo, path, len);
563 : }
564 :
565 260 : TraStatus TraceSafeGetFileName(const TraceStackRecorderInfo *info, char *name, size_t len)
566 : {
567 260 : if ((info == NULL) || (name == NULL) || (len == 0)) {
568 60 : return TRACE_INVALID_PARAM;
569 : }
570 200 : char timeString[TIMESTAMP_MAX_LENGTH] = { 0 };
571 200 : uint64_t fileTime = GetRealTime();
572 200 : TraStatus ret = TimestampToFileStr(fileTime, timeString, TIMESTAMP_MAX_LENGTH);
573 200 : if (ret != TRACE_SUCCESS) {
574 20 : LOGE("get dir time failed, ret=%d", ret);
575 20 : return ret;
576 : }
577 :
578 180 : int32_t err = snprintf_s(name, len, len - 1U, "%s_tracer_%d_%d_%s_%s",
579 180 : TRACER_STACKCORE_NAME, info->signo, info->tid, program_invocation_short_name, timeString);
580 180 : if (err == -1) {
581 20 : LOGE("snprintf_s file name failed, info : %s, signo=%d, tid=%d, name=%s",
582 : strerror(AdiagGetErrorCode()), info->signo, info->tid, program_invocation_short_name);
583 20 : return TRACE_FAILURE;
584 : }
585 160 : return TRACE_SUCCESS;
586 : }
|