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