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 % 195 193
Test Date: 2026-07-28 10:53:44 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         8573 : TraStatus ScdUtilTrim(char *start, uint32_t len, const char **pos)
      27              : {
      28         8573 :     if ((start == NULL) || (len == 0)) {
      29           14 :         return TRACE_FAILURE;
      30              :     }
      31              : 
      32         8559 :     char *end = start + strlen(start);
      33         8559 :     if (start == end) {
      34           14 :         *pos = start;
      35           14 :         return TRACE_SUCCESS;
      36              :     }
      37              : 
      38       134509 :     while ((start < end) && (isspace((int)(*start)) != 0)) {
      39       125964 :         start++;
      40              :     }
      41         8545 :     if (start == end) {
      42         2094 :         *pos = start;
      43         2094 :         return TRACE_SUCCESS;
      44              :     }
      45              : 
      46        12797 :     while ((start < end) && (isspace((int)(*(end - 1))) != 0)) {
      47         6346 :         end--;
      48              :     }
      49              : 
      50         6451 :     *end = '\0';
      51         6451 :     *pos = start;
      52         6451 :     return TRACE_SUCCESS;
      53              : }
      54              : 
      55           42 : TraStatus ScdUtilReadStdin(void *buf, size_t len)
      56              : {
      57           42 :     SCD_CHK_PTR_ACTION(buf, return TRACE_FAILURE);
      58           28 :     size_t readLen = 0;
      59              : 
      60           42 :     while(len > readLen) {
      61           28 :         ssize_t readSize = SCD_UTIL_RETRY(read(STDIN_FILENO, (void *)((uint8_t *)buf + readLen), len - readLen));
      62           28 :         if (readSize <= 0) {
      63           14 :             SCD_DLOG_ERR("read from stdin failed, ret=%ld, errno=%d.", readSize, errno);
      64           14 :             return TRACE_FAILURE;
      65              :         }
      66           14 :         readLen += (size_t)readSize;
      67              :     }
      68           14 :     return TRACE_SUCCESS;
      69              : }
      70              : 
      71        67942 : ssize_t ScdUtilReadLine(int32_t fd, char *buf, size_t len)
      72              : {
      73        67942 :     if (fd < 0 || buf == NULL || len == 0) {
      74           14 :         return -1;
      75              :     }
      76              : 
      77        67928 :     ssize_t n = 1;
      78        67928 :     char c = (char)EOF;
      79        67928 :     char *ptr = buf;
      80      5164435 :     while (n < (ssize_t)len) {
      81      5164210 :         ssize_t rc = read(fd, &c, 1);
      82      5164210 :         if (rc == 1) {
      83      5163061 :             *ptr = c;
      84      5163061 :             ptr++;
      85      5163061 :             if (c == '\n') {
      86        66568 :                 break;
      87              :             }
      88         1149 :         } else if (rc == 0) {
      89         1121 :             *ptr = '\0';
      90         1121 :             return (n - 1);
      91              :         } else {
      92           28 :             if (errno == EINTR) {
      93           14 :                 continue;
      94              :             }
      95           14 :             return -1;
      96              :         }
      97      5096493 :         n++;
      98              :     }
      99        66793 :     *ptr = '\0';
     100        66793 :     return n;
     101              : }
     102              : 
     103          218 : STATIC TraStatus ScdUtilGetTaskName(const char *path, char *buf, size_t len)
     104              : {
     105          218 :     int32_t fd = open(path, O_RDONLY | O_CLOEXEC);
     106          218 :     if (fd < 0) {
     107           29 :         SCD_DLOG_WAR("can not open file[%s], errno=%d.", path, errno);
     108           29 :         return TRACE_FAILURE;
     109              :     }
     110              :     // read a line
     111          189 :     char tmp[SCD_UTIL_TMP_BUF_LEN] = {0};
     112          189 :     ssize_t ret = ScdUtilReadLine(fd, tmp, SCD_UTIL_TMP_BUF_LEN);
     113          189 :     (void)close(fd);
     114          189 :     if (ret <= 0) {
     115           28 :         SCD_DLOG_WAR("can not read line from file[%s], errno=%d.", path, errno);
     116           28 :         return TRACE_FAILURE;
     117              :     }
     118              : 
     119              :     // trim
     120          161 :     const char *data = NULL;
     121          161 :     if ((ScdUtilTrim(tmp, SCD_UTIL_TMP_BUF_LEN, &data) != TRACE_SUCCESS) || (strlen(data) == 0)) {
     122           14 :         SCD_DLOG_WAR("file line is empty.");
     123           14 :         return TRACE_FAILURE;
     124              :     }
     125          147 :     size_t dataLen = strlen(data);
     126          147 :     size_t copyLen = SCD_MIN(len - 1U, dataLen);
     127          147 :     errno_t err = strncpy_s(buf, len, data, copyLen);
     128          147 :     if (err != EOK) {
     129           14 :         SCD_DLOG_WAR("can not strncpy_s, ret=%d, errno=%d", (int32_t)err, errno);
     130           14 :         return TRACE_FAILURE;
     131              :     }
     132              : 
     133          133 :     buf[copyLen] = '\0';
     134          133 :     return TRACE_SUCCESS;
     135              : }
     136              : 
     137          142 : STATIC void ScdUtilSetUnknown(char *buf, size_t len)
     138              : {
     139          142 :     errno_t ret = strncpy_s(buf, len, "unknown", strlen("unknown"));
     140          142 :     if (ret != 0) {
     141           28 :         SCD_DLOG_ERR("strncpy_s failed. (ret=%d)\n", (int32_t)ret);
     142              :     }
     143          142 : }
     144              : 
     145          233 : void ScdUtilGetProcessName(int32_t pid, char *buf, size_t len)
     146              : {
     147          233 :     char path[SCD_UTIL_TMP_BUF_LEN] = {0};
     148              : 
     149          233 :     int32_t ret = snprintf_s(path, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%d/cmdline", pid);
     150          233 :     if (ret == -1) {
     151           43 :         SCD_DLOG_WAR("can not snprintf_s, set process name to unknown.");
     152           43 :         ScdUtilSetUnknown(buf, len);
     153           43 :         return;
     154              :     }
     155              : 
     156          190 :     if (ScdUtilGetTaskName(path, buf, len) != TRACE_SUCCESS) {
     157           71 :         SCD_DLOG_WAR("can not get process name by file[%s], set process name to unknown.", path);
     158           71 :         ScdUtilSetUnknown(buf, len);
     159              :     }
     160              : }
     161              : 
     162           42 : void ScdUtilGetThreadName(int32_t pid, int32_t tid, char *buf, size_t len)
     163              : {
     164           42 :     char path[SCD_UTIL_TMP_BUF_LEN] = {0};
     165           42 :     int32_t ret = snprintf_s(path, sizeof(path), sizeof(path) - 1U, "/proc/%d/task/%d/comm", pid, tid);
     166           42 :     if (ret == -1) {
     167           14 :         SCD_DLOG_WAR("can not snprintf_s, set thread name to unknown.");
     168           14 :         ScdUtilSetUnknown(buf, len);
     169           14 :         return;
     170              :     }
     171              : 
     172           28 :     if (ScdUtilGetTaskName(path, buf, len) != TRACE_SUCCESS) {
     173           14 :         SCD_DLOG_WAR("can not get thread name by file[%s], set thread name to unknown.", path);
     174           14 :         ScdUtilSetUnknown(buf, len);
     175              :     }
     176              : }
     177              : 
     178           29 : STATIC TraStatus ScdUtilPtraceReadLong(int32_t pid, uintptr_t addr, long *value)
     179              : {
     180           29 :     errno = 0;
     181           29 :     long ret = ptrace(PTRACE_PEEKTEXT, pid, addr, NULL);
     182           29 :     if (ret == -1 && errno != 0) {
     183            7 :         SCD_DLOG_ERR("ptrace peektext failed, ret %ld, error : %s", ret, strerror(errno));
     184            7 :         return TRACE_FAILURE; 
     185              :     }
     186           22 :     *value = ret;
     187           22 :     return TRACE_SUCCESS;
     188              : }
     189              : 
     190           20 : size_t ScdUtilsPtraceRead(int32_t pid, uintptr_t src, void *dst, size_t dstLen)
     191              : {
     192           20 :     size_t readSize = dstLen;
     193           20 :     void *dstPos = dst;
     194           20 :     uintptr_t srcAddr = src;
     195           20 :     long data = 0;
     196           20 :     size_t alignBytes = srcAddr & (sizeof(long) - 1U);
     197           20 :     if (alignBytes != 0) {
     198           14 :         TraStatus ret = ScdUtilPtraceReadLong(pid, srcAddr & ~(sizeof(long) - 1U), &data);
     199           14 :         if (ret != TRACE_SUCCESS) {
     200            7 :             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         1603 : int32_t ScdUtilOpen(const char *path)
     242              : {
     243         1603 :     char realPath[TRACE_MAX_PATH] = {0};
     244         1603 :     if ((TraceRealPath(path, realPath, TRACE_MAX_PATH) != EN_OK) && (AdiagGetErrorCode() != ENOENT)) {
     245           29 :         SCD_DLOG_ERR("can not get realpath, path=%s, strerr=%s.", path, strerror(AdiagGetErrorCode()));
     246           29 :         return -1;
     247              :     }
     248              : 
     249         1574 :     int32_t fd = open(path, O_RDONLY | O_CLOEXEC);
     250         1574 :     if (fd < 0) {
     251           89 :         SCD_DLOG_ERR("open %s failed, stderr=%s.", path, strerror(AdiagGetErrorCode()));
     252           89 :         return -1;
     253              :     }
     254         1485 :     return fd;
     255              : }
     256              : 
     257        29325 : size_t ScdUtilWrite(int32_t fd, const void *data, size_t len)
     258              : {
     259        29325 :     if ((fd < 0) || (data == NULL) || (len == 0)) {
     260          359 :         SCD_DLOG_ERR("invalid input, fd=%d, data=%p, len=%zu.", fd, data, len);
     261          359 :         return 0;
     262              :     }
     263              : 
     264        28966 :     size_t reserved = len;
     265              :     do {
     266        28966 :         ssize_t wrLen = write(fd, (const void *)((uintptr_t)data + (len - reserved)), reserved);
     267        28966 :         if ((wrLen < 0) || (errno == EINTR)) {
     268           14 :             SCD_DLOG_ERR("write failed, ret=%ld, errno=%d.", wrLen, errno);
     269           14 :             return len - reserved;
     270              :         }
     271        28952 :         reserved -= (size_t)wrLen;
     272        28952 :     } while (reserved != 0);
     273        28952 :     return len;
     274              : }
     275              : 
     276          851 : void ScdUtilWriteTitle(int32_t fd, const char *title)
     277              : {
     278          851 :     (void)ScdUtilWrite(fd, title, strlen(title));
     279          851 :     ScdUtilWriteNewLine(fd);
     280          851 : }
     281              : 
     282         1822 : void ScdUtilWriteNewLine(int32_t fd)
     283              : {
     284         1822 :     (void)ScdUtilWrite(fd, "\n", 1);
     285         1822 : }
     286              : 
     287         1422 : int32_t ScdUtilGetProcFd(int32_t pid, const char* fileName)
     288              : {
     289         1422 :     char path[SCD_UTIL_TMP_BUF_LEN] = {0};
     290              :     int32_t err;
     291         1422 :     if (pid == -1) {
     292          360 :         err = snprintf_s(path, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%s", fileName);
     293              :     } else {
     294         1062 :         err = snprintf_s(path, SCD_UTIL_TMP_BUF_LEN, SCD_UTIL_TMP_BUF_LEN - 1U, "/proc/%d/%s", pid, fileName);
     295              :     }
     296         1422 :     if (err == -1) {
     297           29 :         SCD_DLOG_ERR("snprintf_s proc file name failed, pid=%d, file name[%s].", pid, fileName);
     298           29 :         return -1;
     299              :     }
     300              : 
     301         1393 :     return ScdUtilOpen(path);
     302              : }
     303              : 
     304          162 : TraStatus ScdUtilWriteProcInfo(int32_t fd, int32_t pid, const char* fileName)
     305              : {
     306          162 :     int32_t procFd = ScdUtilGetProcFd(pid, fileName);
     307          162 :     if (procFd < 0) {
     308           28 :         return TRACE_FAILURE;
     309              :     }
     310              : 
     311          134 :     char info[SCD_UTIL_TMP_BUF_LEN] = { 0 };
     312         7844 :     while (ScdUtilReadLine(procFd, info, SCD_UTIL_TMP_BUF_LEN) > 0) {
     313         7724 :         size_t ret = ScdUtilWrite(fd, info, strlen(info));
     314         7724 :         if (ret != strlen(info)) {
     315           14 :             SCD_DLOG_ERR("write proc info to file failed, ret=%d, errno=%d", ret, errno);
     316           14 :             (void)close(procFd);
     317           14 :             return TRACE_FAILURE;
     318              :         }
     319              :     }
     320              : 
     321          120 :     SCD_DLOG_INF("write proc file[%s] info to file successfully.", fileName);
     322          120 :     (void)close(procFd);
     323          120 :     return TRACE_SUCCESS;
     324              : }
        

Generated by: LCOV version 2.0-1