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_maps.h"
12 : #include "scd_map.h"
13 : #include "scd_log.h"
14 : #include "adiag_list.h"
15 : #include "scd_util.h"
16 : #include "atrace_types.h"
17 : #include "trace_system_api.h"
18 :
19 : #define SCD_MAPS_BUF_LEN 512U
20 :
21 : STATIC ScdMaps g_maps;
22 :
23 80 : ScdMaps *ScdMapsGet(void)
24 : {
25 80 : return &g_maps;
26 : }
27 :
28 29600 : STATIC TraStatus ScdMapsCmpName(const void *nodeData, const void *data)
29 : {
30 29600 : const ScdMap *node = (const ScdMap *)nodeData;
31 29600 : const char *name = (const char *)data;
32 29600 : if (strcmp(node->name, name) == 0) {
33 5280 : return TRACE_SUCCESS;
34 : }
35 24320 : return TRACE_FAILURE;
36 : }
37 :
38 6192 : STATIC ScdMap *ScdMapsGetMapByName(ScdMaps *maps, const char *name)
39 : {
40 6192 : return AdiagListForEach(&maps->mapList, ScdMapsCmpName, name);
41 : }
42 :
43 0 : STATIC TraStatus ScdMapsCmpPcRange(const void *nodeData, const void *data)
44 : {
45 0 : const ScdMap *node = (const ScdMap *)nodeData;
46 0 : uintptr_t pc = (uintptr_t)data;
47 0 : if (pc >= node->start && pc < node->end) {
48 0 : return TRACE_SUCCESS;
49 : }
50 0 : return TRACE_FAILURE;
51 : }
52 :
53 0 : ScdMap *ScdMapsGetMapByPc(ScdMaps *maps, uintptr_t pc)
54 : {
55 0 : return AdiagListForEach(&maps->mapList, ScdMapsCmpPcRange, (const void *)pc);
56 : }
57 :
58 10386 : STATIC ScdMap *ScdMapsParseLine(ScdMaps *maps, char *line, uint32_t len)
59 : {
60 10386 : uintptr_t start = 0;
61 10386 : uintptr_t end = 0;
62 10386 : size_t offset = 0;
63 10386 : int32_t pos = 0;
64 :
65 : // scan
66 10386 : int32_t ret = sscanf_s(line, "%lx-%lx %*s %lx %*x:%*x %*d%n", &start, &end, &offset, &pos);
67 10386 : if ((ret <= 0) || (pos >= (int32_t)len) || (pos <= 0)) {
68 2016 : SCD_DLOG_ERR("sscanf_s failed, ret = %d, line = %s.", ret, line);
69 2016 : return NULL;
70 : }
71 :
72 8370 : const char *name = NULL;
73 8370 : if (ScdUtilTrim(line + pos, len - (uint32_t)pos, &name) != TRACE_SUCCESS) {
74 0 : return NULL;
75 : }
76 8370 : if ((name == NULL) || (strlen(name) == 0)) {
77 2080 : return NULL;
78 : }
79 6290 : char realPath[TRACE_MAX_PATH] = { 0 };
80 6290 : errno = 0;
81 6290 : if ((TraceRealPath(name, realPath, TRACE_MAX_PATH) != EN_OK) && (errno != ENOENT)) {
82 98 : SCD_DLOG_ERR("can not get realpath, path=%s, strerr=%s.", name, strerror(errno));
83 98 : return NULL;
84 : }
85 :
86 : // find map
87 6192 : ScdMap *map = ScdMapsGetMapByName(maps, realPath);
88 6192 : if (map != NULL) {
89 : // the start and end of the multi-segment code segment of the map are updated each time
90 5280 : if (ScdMapUpdata(map, start, end, offset) == TRACE_SUCCESS) {
91 5280 : return NULL;
92 : }
93 : }
94 : // create map
95 912 : return ScdMapCreate(start, end, offset, realPath);
96 : }
97 :
98 : /**
99 : * @brief load maps
100 : * @param [in] maps: maps info
101 : * @return TraStatus
102 : */
103 129 : TraStatus ScdMapsLoad(ScdMaps *maps)
104 : {
105 129 : char buf[SCD_MAPS_BUF_LEN] = {0};
106 129 : int32_t err = snprintf_s(buf, SCD_MAPS_BUF_LEN, SCD_MAPS_BUF_LEN - 1U, "/proc/%d/maps", maps->pid);
107 129 : if (err == -1) {
108 16 : SCD_DLOG_ERR("snprintf_s failed, get maps file name failed.");
109 16 : return TRACE_FAILURE;
110 : }
111 :
112 113 : FILE *fp = fopen(buf, "r");
113 113 : if (fp == NULL) {
114 16 : SCD_DLOG_ERR("open maps file failed.");
115 16 : return TRACE_FAILURE;
116 : }
117 :
118 10467 : while (fgets(buf, SCD_MAPS_BUF_LEN, fp) != NULL) {
119 10386 : ScdMap *node = ScdMapsParseLine(maps, buf, SCD_MAPS_BUF_LEN);
120 10386 : if (node == NULL) {
121 9474 : continue;
122 : }
123 :
124 912 : AdiagStatus ret = AdiagListInsert(&maps->mapList, node);
125 912 : if (ret != ADIAG_SUCCESS) {
126 16 : SCD_DLOG_ERR("add map to map list failed.");
127 16 : ScdMapDestroy(&node);
128 16 : (void)fclose(fp);
129 16 : return TRACE_FAILURE;
130 : }
131 : }
132 :
133 81 : (void)fclose(fp);
134 81 : return TRACE_SUCCESS;
135 : }
136 :
137 : /**
138 : * @brief init maps
139 : * @param [in] maps: maps info
140 : * @param [in] pid: process id
141 : * @return TraStatus
142 : */
143 370 : TraStatus ScdMapsInit(ScdMaps *maps, int32_t pid)
144 : {
145 370 : SCD_CHK_PTR_ACTION(maps, return TRACE_FAILURE);
146 :
147 370 : maps->pid = pid;
148 370 : AdiagStatus adiagRet = AdiagListInit(&maps->mapList);
149 370 : if (adiagRet != ADIAG_SUCCESS) {
150 16 : SCD_DLOG_ERR("init maps list failed.");
151 16 : return TRACE_FAILURE;
152 : }
153 354 : return TRACE_SUCCESS;
154 : }
155 :
156 : /**
157 : * @brief init maps
158 : * @param [in] maps: maps info
159 : * @return NA
160 : */
161 354 : void ScdMapsUninit(ScdMaps *maps)
162 : {
163 354 : ScdMap *node = (ScdMap *)AdiagListTakeOut(&maps->mapList);
164 1250 : while (node != NULL) {
165 896 : ScdMapDestroy(&node);
166 896 : node = (ScdMap *)AdiagListTakeOut(&maps->mapList);
167 : }
168 354 : }
|