LCOV - code coverage report
Current view: top level - atrace/utrace/stacktrace/stacktrace_dumper - scd_util.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 99.0 % 193 191
Test Date: 2026-08-31 10:07:06 Functions: 100.0 % 15 15

            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 "scd_util.h"
      12              : #include <stdio.h>
      13              : #include <fcntl.h>
      14              : #include <errno.h>
      15              : #include <stdio.h>
      16              : #include <ctype.h>
      17              : #include <sys/ptrace.h>
      18              : #include "securec.h"
      19              : #include "adiag_utils.h"
      20              : #include "trace_system_api.h"
      21              : #include "atrace_types.h"
      22              : #include "scd_log.h"
      23              : 
      24              : #define MIN(a, b) ((a) > (b) ? (b) : (a))
      25              : 
      26        10306 : TraStatus ScdUtilTrim(char* start, uint32_t len, const char** pos)
      27              : {
      28        10306 :     if ((start == NULL) || (len == 0)) {
      29           17 :         return TRACE_FAILURE;
      30              :     }
      31              : 
      32        10289 :     char* end = start + strlen(start);
      33        10289 :     if (start == end) {
      34           17 :         *pos = start;
      35           17 :         return TRACE_SUCCESS;
      36              :     }
      37              : 
      38       159352 :     while ((start < end) && (isspace((int)(*start)) != 0)) {
      39       149080 :         start++;
      40              :     }
      41        10272 :     if (start == end) {
      42         2609 :         *pos = start;
      43         2609 :         return TRACE_SUCCESS;
      44              :     }
      45              : 
      46        15190 :     while ((start < end) && (isspace((int)(*(end - 1))) != 0)) {
      47         7527 :         end--;
      48              :     }
      49              : 
      50         7663 :     *end = '\0';
      51         7663 :     *pos = start;
      52         7663 :     return TRACE_SUCCESS;
      53              : }
      54              : 
      55           51 : TraStatus ScdUtilReadStdin(void* buf, size_t len)
      56              : {
      57           51 :     SCD_CHK_PTR_ACTION(buf, return TRACE_FAILURE);
      58           34 :     size_t readLen = 0;
      59              : 
      60           51 :     while (len > readLen) {
      61           34 :         ssize_t readSize = SCD_UTIL_RETRY(read(STDIN_FILENO, (void*)((uint8_t*)buf + readLen), len - readLen));
      62           34 :         if (readSize <= 0) {
      63           17 :             SCD_DLOG_ERR("read from stdin failed, ret=%ld, errno=%d.", readSize, errno);
      64           17 :             return TRACE_FAILURE;
      65              :         }
      66           17 :         readLen += (size_t)readSize;
      67              :     }
      68           17 :     return TRACE_SUCCESS;
      69              : }
      70              : 
      71        79753 : ssize_t ScdUtilReadLine(int32_t fd, char* buf, size_t len)
      72              : {
      73        79753 :     if (fd < 0 || buf == NULL || len == 0) {
      74           17 :         return -1;
      75              :     }
      76              : 
      77        79736 :     ssize_t n = 1;
      78        79736 :     char c = (char)EOF;
      79        79736 :     char* ptr = buf;
      80      6001810 :     while (n < (ssize_t)len) {
      81      6001538 :         ssize_t rc = read(fd, &c, 1);
      82      6001538 :         if (rc == 1) {
      83      6000144 :             *ptr = c;
      84      6000144 :             ptr++;
      85      6000144 :             if (c == '\n') {
      86        78087 :                 break;
      87              :             }
      88         1394 :         } else if (rc == 0) {
      89         1360 :             *ptr = '\0';
      90         1360 :             return (n - 1);
      91              :         } else {
      92           34 :             if (errno == EINTR) {
      93           17 :                 continue;
      94              :             }
      95           17 :             return -1;
      96              :         }
      97      5922057 :         n++;
      98              :     }
      99        78359 :     *ptr = '\0';
     100        78359 :     return n;
     101              : }
     102              : 
     103          286 : STATIC TraStatus ScdUtilGetTaskName(const char* path, char* buf, size_t len)
     104              : {
     105          286 :     int32_t fd = open(path, O_RDONLY | O_CLOEXEC);
     106          286 :     if (fd < 0) {
     107           42 :         SCD_DLOG_WAR("can not open file[%s], errno=%d.", path, errno);
     108           42 :         return TRACE_FAILURE;
     109              :     }
     110              :     // read a line
     111          244 :     char tmp[SCD_UTIL_TMP_BUF_LEN] = {0};
     112          244 :     ssize_t ret = ScdUtilReadLine(fd, tmp, SCD_UTIL_TMP_BUF_LEN);
     113          244 :     (void)close(fd);
     114          244 :     if (ret <= 0) {
     115           34 :         SCD_DLOG_WAR("can not read line from file[%s], errno=%d.", path, errno);
     116           34 :         return TRACE_FAILURE;
     117              :     }
     118              : 
     119              :     // trim
     120          210 :     const char* data = NULL;
     121          210 :     if ((ScdUtilTrim(tmp, SCD_UTIL_TMP_BUF_LEN, &data) != TRACE_SUCCESS) || (strlen(data) == 0)) {
     122           17 :         SCD_DLOG_WAR("file line is empty.");
     123           17 :         return TRACE_FAILURE;
     124              :     }
     125          193 :     size_t dataLen = strlen(data);
     126          193 :     size_t copyLen = SCD_MIN(len - 1U, dataLen);
     127          193 :     errno_t err = strncpy_s(buf, len, data, copyLen);
     128          193 :     if (err != EOK) {
     129           17 :         SCD_DLOG_WAR("can not strncpy_s, ret=%d, errno=%d", (int32_t)err, errno);
     130           17 :         return TRACE_FAILURE;
     131              :     }
     132              : 
     133          176 :     buf[copyLen] = '\0';
     134          176 :     return TRACE_SUCCESS;
     135              : }
     136              : 
     137          178 : STATIC void ScdUtilSetUnknown(char* buf, size_t len)
     138              : {
     139          178 :     errno_t ret = strncpy_s(buf, len, "unknown", strlen("unknown"));
     140          178 :     if (ret != 0) {
     141           34 :         SCD_DLOG_ERR("strncpy_s failed. (ret=%d)\n", (int32_t)ret);
     142              :     }
     143          178 : }
     144              : 
     145          289 : void ScdUtilGetProcessName(int32_t pid, char* buf, size_t len)
     146              : {
     147          289 :     char path[SCD_UTIL_TMP_BUF_LEN] = {0};
     148              : 
     149          289 :     int32_t ret = snprintf_s(path, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%d/cmdline", pid);
     150          289 :     if (ret == -1) {
     151           51 :         SCD_DLOG_WAR("can not snprintf_s, set process name to unknown.");
     152           51 :         ScdUtilSetUnknown(buf, len);
     153           51 :         return;
     154              :     }
     155              : 
     156          238 :     if (ScdUtilGetTaskName(path, buf, len) != TRACE_SUCCESS) {
     157           85 :         SCD_DLOG_WAR("can not get process name by file[%s], set process name to unknown.", path);
     158           85 :         ScdUtilSetUnknown(buf, len);
     159              :     }
     160              : }
     161              : 
     162           65 : void ScdUtilGetThreadName(int32_t pid, int32_t tid, char* buf, size_t len)
     163              : {
     164           65 :     char path[SCD_UTIL_TMP_BUF_LEN] = {0};
     165           65 :     int32_t ret = snprintf_s(path, sizeof(path), sizeof(path) - 1U, "/proc/%d/task/%d/comm", pid, tid);
     166           65 :     if (ret == -1) {
     167           17 :         SCD_DLOG_WAR("can not snprintf_s, set thread name to unknown.");
     168           17 :         ScdUtilSetUnknown(buf, len);
     169           17 :         return;
     170              :     }
     171              : 
     172           48 :     if (ScdUtilGetTaskName(path, buf, len) != TRACE_SUCCESS) {
     173           25 :         SCD_DLOG_WAR("can not get thread name by file[%s], set thread name to unknown.", path);
     174           25 :         ScdUtilSetUnknown(buf, len);
     175              :     }
     176              : }
     177              : 
     178           32 : STATIC TraStatus ScdUtilPtraceReadLong(int32_t pid, uintptr_t addr, long* value)
     179              : {
     180           32 :     errno = 0;
     181           32 :     long ret = ptrace(PTRACE_PEEKTEXT, pid, addr, NULL);
     182           32 :     if (ret == -1 && errno != 0) {
     183           10 :         SCD_DLOG_ERR("ptrace peektext failed, ret %ld, error : %s", ret, strerror(errno));
     184           10 :         return TRACE_FAILURE;
     185              :     }
     186           22 :     *value = ret;
     187           22 :     return TRACE_SUCCESS;
     188              : }
     189              : 
     190           23 : size_t ScdUtilsPtraceRead(int32_t pid, uintptr_t src, void* dst, size_t dstLen)
     191              : {
     192           23 :     size_t readSize = dstLen;
     193           23 :     void* dstPos = dst;
     194           23 :     uintptr_t srcAddr = src;
     195           23 :     long data = 0;
     196           23 :     size_t alignBytes = srcAddr & (sizeof(long) - 1U);
     197           23 :     if (alignBytes != 0) {
     198           17 :         TraStatus ret = ScdUtilPtraceReadLong(pid, srcAddr & ~(sizeof(long) - 1U), &data);
     199           17 :         if (ret != TRACE_SUCCESS) {
     200           10 :             return 0;
     201              :         }
     202            7 :         size_t readLen = MIN(readSize, sizeof(long) - alignBytes);
     203            7 :         errno_t err = memcpy_s(dstPos, readSize, (const void*)((uintptr_t)(&data) + alignBytes), readLen);
     204            7 :         if (err != EOK) {
     205            2 :             SCD_DLOG_ERR("memcpy_s failed, err = %d, errno = %d.", (int32_t)err, errno);
     206            2 :             return 0;
     207              :         }
     208            5 :         srcAddr += readLen;
     209            5 :         dstPos = (void*)((uintptr_t)dstPos + readLen);
     210            5 :         readSize -= readLen;
     211              :     }
     212              : 
     213           18 :     for (size_t i = readSize / sizeof(long); i > 0; i--) {
     214            8 :         TraStatus ret = ScdUtilPtraceReadLong(pid, srcAddr, &data);
     215            8 :         if (ret != TRACE_SUCCESS) {
     216            0 :             return 0;
     217              :         }
     218            8 :         errno_t err = memcpy_s(dstPos, readSize, &data, sizeof(long));
     219            8 :         if (err != EOK) {
     220            1 :             SCD_DLOG_ERR("memcpy_s failed, err = %d, errno = %d.", (int32_t)err, errno);
     221            1 :             return 0;
     222              :         }
     223            7 :         srcAddr += sizeof(long);
     224            7 :         dstPos = (void*)((uintptr_t)dstPos + sizeof(long));
     225            7 :         readSize -= sizeof(long);
     226              :     }
     227           10 :     if (readSize != 0) {
     228            7 :         TraStatus ret = ScdUtilPtraceReadLong(pid, srcAddr, &data);
     229            7 :         if (ret != TRACE_SUCCESS) {
     230            0 :             return 0;
     231              :         }
     232            7 :         errno_t err = memcpy_s(dstPos, readSize, &data, readSize);
     233            7 :         if (err != EOK) {
     234            1 :             SCD_DLOG_ERR("memcpy_s failed, err = %d, errno = %d.", (int32_t)err, errno);
     235            1 :             return 0;
     236              :         }
     237              :     }
     238            9 :     return dstLen;
     239              : }
     240              : 
     241         1900 : int32_t ScdUtilOpen(const char* path)
     242              : {
     243         1900 :     char realPath[TRACE_MAX_PATH] = {0};
     244         1900 :     if ((TraceRealPath(path, realPath, TRACE_MAX_PATH) != EN_OK) && (AdiagGetErrorCode() != ENOENT)) {
     245           34 :         SCD_DLOG_ERR("can not get realpath, path=%s, strerr=%s.", path, strerror(AdiagGetErrorCode()));
     246           34 :         return -1;
     247              :     }
     248              : 
     249         1866 :     int32_t fd = open(path, O_RDONLY | O_CLOEXEC);
     250         1866 :     if (fd < 0) {
     251          105 :         SCD_DLOG_ERR("open %s failed, stderr=%s.", path, strerror(AdiagGetErrorCode()));
     252          105 :         return -1;
     253              :     }
     254         1761 :     return fd;
     255              : }
     256              : 
     257        37283 : size_t ScdUtilWrite(int32_t fd, const void* data, size_t len)
     258              : {
     259        37283 :     if ((fd < 0) || (data == NULL) || (len == 0)) {
     260          408 :         SCD_DLOG_ERR("invalid input, fd=%d, data=%p, len=%zu.", fd, data, len);
     261          408 :         return 0;
     262              :     }
     263              : 
     264        36875 :     size_t reserved = len;
     265              :     do {
     266        36875 :         ssize_t wrLen = write(fd, (const void*)((uintptr_t)data + (len - reserved)), reserved);
     267        36875 :         if ((wrLen < 0) || (errno == EINTR)) {
     268           17 :             SCD_DLOG_ERR("write failed, ret=%ld, errno=%d.", wrLen, errno);
     269           17 :             return len - reserved;
     270              :         }
     271        36858 :         reserved -= (size_t)wrLen;
     272        36858 :     } while (reserved != 0);
     273        36858 :     return len;
     274              : }
     275              : 
     276         1061 : void ScdUtilWriteTitle(int32_t fd, const char* title)
     277              : {
     278         1061 :     (void)ScdUtilWrite(fd, title, strlen(title));
     279         1061 :     ScdUtilWriteNewLine(fd);
     280         1061 : }
     281              : 
     282         2245 : void ScdUtilWriteNewLine(int32_t fd) { (void)ScdUtilWrite(fd, "\n", 1); }
     283              : 
     284         1683 : int32_t ScdUtilGetProcFd(int32_t pid, const char* fileName)
     285              : {
     286         1683 :     char path[SCD_UTIL_TMP_BUF_LEN] = {0};
     287              :     int32_t err;
     288         1683 :     if (pid == -1) {
     289          425 :         err = snprintf_s(path, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%s", fileName);
     290              :     } else {
     291         1258 :         err = snprintf_s(path, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%d/%s", pid, fileName);
     292              :     }
     293         1683 :     if (err == -1) {
     294           34 :         SCD_DLOG_ERR("snprintf_s proc file name failed, pid=%d, file name[%s].", pid, fileName);
     295           34 :         return -1;
     296              :     }
     297              : 
     298         1649 :     return ScdUtilOpen(path);
     299              : }
     300              : 
     301          255 : TraStatus ScdUtilWriteProcInfo(int32_t fd, int32_t pid, const char* fileName)
     302              : {
     303          255 :     int32_t procFd = ScdUtilGetProcFd(pid, fileName);
     304          255 :     if (procFd < 0) {
     305           34 :         return TRACE_FAILURE;
     306              :     }
     307              : 
     308          221 :     char info[SCD_UTIL_TMP_BUF_LEN] = {0};
     309        13022 :     while (ScdUtilReadLine(procFd, info, SCD_UTIL_TMP_BUF_LEN) > 0) {
     310        12818 :         size_t ret = ScdUtilWrite(fd, info, strlen(info));
     311        12818 :         if (ret != strlen(info)) {
     312           17 :             SCD_DLOG_ERR("write proc info to file failed, ret=%d, errno=%d", ret, errno);
     313           17 :             (void)close(procFd);
     314           17 :             return TRACE_FAILURE;
     315              :         }
     316              :     }
     317              : 
     318          204 :     SCD_DLOG_INF("write proc file[%s] info to file successfully.", fileName);
     319          204 :     (void)close(procFd);
     320          204 :     return TRACE_SUCCESS;
     321              : }
        

Generated by: LCOV version 2.0-1