1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hidebug/hidebug.h"
17
18 #include <memory>
19 #include <string>
20
21 #include "hidebug/hidebug_type.h"
22 #include "hidebug_native_interface.h"
23 #include "securec.h"
24 #ifdef HOOK_ENABLE
25 #include "musl_preinit_common.h"
26 static volatile struct MallocDispatchType *g_lastDispatchTable = nullptr;
27 static struct HiDebug_MallocDispatch g_defaultDispatchDatable = {
28 .malloc = __libc_malloc_default_dispatch.malloc,
29 .calloc = __libc_malloc_default_dispatch.calloc,
30 .realloc = __libc_malloc_default_dispatch.realloc,
31 .free = __libc_malloc_default_dispatch.free,
32 .mmap = __libc_malloc_default_dispatch.mmap,
33 .munmap = __libc_malloc_default_dispatch.munmap,
34 };
35 static struct MallocDispatchType g_currentDispatchDatable = __libc_malloc_default_dispatch;
36 #endif
OH_HiDebug_GetAppCpuUsage()37 double OH_HiDebug_GetAppCpuUsage()
38 {
39 return OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetCpuUsage();
40 }
41
OH_HiDebug_GetSystemCpuUsage()42 double OH_HiDebug_GetSystemCpuUsage()
43 {
44 auto cpuUsageOptional = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetSystemCpuUsage();
45 if (cpuUsageOptional) {
46 return cpuUsageOptional.value();
47 }
48 return 0;
49 }
50
OH_HiDebug_GetAppThreadCpuUsage()51 HiDebug_ThreadCpuUsagePtr OH_HiDebug_GetAppThreadCpuUsage()
52 {
53 auto threadMap = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetAppThreadCpuUsage();
54 HiDebug_ThreadCpuUsagePtr head = nullptr;
55 HiDebug_ThreadCpuUsagePtr prev = nullptr;
56 for (const auto[threadId, cpuUsage] : threadMap) {
57 HiDebug_ThreadCpuUsagePtr node = (HiDebug_ThreadCpuUsagePtr) malloc(sizeof(HiDebug_ThreadCpuUsage));
58 if (node == nullptr) {
59 continue;
60 }
61 node->threadId = threadId;
62 node->cpuUsage = cpuUsage;
63 node->next = nullptr;
64 if (prev == nullptr) {
65 head = node;
66 } else {
67 prev->next = node;
68 }
69 prev = node;
70 }
71 return head;
72 }
73
OH_HiDebug_FreeThreadCpuUsage(HiDebug_ThreadCpuUsagePtr * threadCpuUsage)74 void OH_HiDebug_FreeThreadCpuUsage(HiDebug_ThreadCpuUsagePtr *threadCpuUsage)
75 {
76 if (threadCpuUsage == nullptr || *threadCpuUsage == nullptr) {
77 return;
78 }
79 HiDebug_ThreadCpuUsagePtr node = *threadCpuUsage;
80 while (node != nullptr) {
81 HiDebug_ThreadCpuUsagePtr next = node->next;
82 free(node);
83 node = next;
84 }
85 *threadCpuUsage = nullptr;
86 }
87
OH_HiDebug_GetAppMemoryLimit(HiDebug_MemoryLimit * memoryLimit)88 void OH_HiDebug_GetAppMemoryLimit(HiDebug_MemoryLimit *memoryLimit)
89 {
90 if (!memoryLimit) {
91 return;
92 }
93 auto memoryLimitOption = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetAppMemoryLimit();
94 if (memoryLimitOption) {
95 memoryLimit->vssLimit = memoryLimitOption->vssLimit;
96 memoryLimit->rssLimit = memoryLimitOption->rssLimit;
97 }
98 }
99
OH_HiDebug_GetAppNativeMemInfoWithCache(HiDebug_NativeMemInfo * nativeMemInfo,bool forceRefresh)100 void OH_HiDebug_GetAppNativeMemInfoWithCache(HiDebug_NativeMemInfo *nativeMemInfo, bool forceRefresh)
101 {
102 if (!nativeMemInfo) {
103 return;
104 }
105 auto memInfoOption = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(!forceRefresh);
106 if (memInfoOption) {
107 nativeMemInfo->pss = memInfoOption->pss;
108 nativeMemInfo->rss = memInfoOption->rss;
109 nativeMemInfo->sharedDirty = memInfoOption->sharedDirty;
110 nativeMemInfo->privateDirty = memInfoOption->privateDirty;
111 nativeMemInfo->sharedClean = memInfoOption->sharedClean;
112 nativeMemInfo->privateClean = memInfoOption->privateClean;
113 nativeMemInfo->vss = memInfoOption->vss;
114 }
115 }
116
OH_HiDebug_GetAppNativeMemInfo(HiDebug_NativeMemInfo * nativeMemInfo)117 void OH_HiDebug_GetAppNativeMemInfo(HiDebug_NativeMemInfo *nativeMemInfo)
118 {
119 OH_HiDebug_GetAppNativeMemInfoWithCache(nativeMemInfo, true);
120 }
121
OH_HiDebug_GetSystemMemInfo(HiDebug_SystemMemInfo * systemMemInfo)122 void OH_HiDebug_GetSystemMemInfo(HiDebug_SystemMemInfo *systemMemInfo)
123 {
124 if (!systemMemInfo) {
125 return;
126 }
127 auto sysMemInfo = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetSystemMemInfo();
128 if (sysMemInfo) {
129 systemMemInfo->totalMem = sysMemInfo->totalMem;
130 systemMemInfo->freeMem = sysMemInfo->freeMem;
131 systemMemInfo->availableMem = sysMemInfo->availableMem;
132 }
133 }
134
ConvertTraceErrorCode(OHOS::HiviewDFX::TraceErrorCode traceErrorCode)135 HiDebug_ErrorCode ConvertTraceErrorCode(OHOS::HiviewDFX::TraceErrorCode traceErrorCode)
136 {
137 switch (traceErrorCode) {
138 case OHOS::HiviewDFX::TRACE_SUCCESS:
139 return HIDEBUG_SUCCESS;
140 case OHOS::HiviewDFX::TRACE_INVALID_ARGUMENT:
141 return HIDEBUG_INVALID_ARGUMENT;
142 case OHOS::HiviewDFX::TRACE_CAPTURED_ALREADY:
143 return HIDEBUG_TRACE_CAPTURED_ALREADY;
144 case OHOS::HiviewDFX::TRACE_NO_PERMISSION:
145 return HIDEBUG_NO_PERMISSION;
146 case OHOS::HiviewDFX::NO_TRACE_RUNNING:
147 return HIDEBUG_NO_TRACE_RUNNING;
148 default:
149 return HIDEBUG_TRACE_ABNORMAL;
150 }
151 }
152
OH_HiDebug_StartAppTraceCapture(HiDebug_TraceFlag flag,uint64_t tags,uint32_t limitSize,char * fileName,uint32_t length)153 HiDebug_ErrorCode OH_HiDebug_StartAppTraceCapture(HiDebug_TraceFlag flag,
154 uint64_t tags, uint32_t limitSize, char* fileName, uint32_t length)
155 {
156 if (fileName == nullptr) {
157 return HIDEBUG_INVALID_ARGUMENT;
158 }
159 auto& nativeInterface = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance();
160 std::string file;
161 auto ret = nativeInterface.StartAppTraceCapture(tags, flag, limitSize, file);
162 if (ret != OHOS::HiviewDFX::TRACE_SUCCESS) {
163 return ConvertTraceErrorCode(ret);
164 }
165 if (strcpy_s(fileName, length, file.c_str()) != EOK) {
166 nativeInterface.StopAppTraceCapture();
167 return HIDEBUG_INVALID_ARGUMENT;
168 }
169 return HIDEBUG_SUCCESS;
170 }
171
OH_HiDebug_StopAppTraceCapture()172 HiDebug_ErrorCode OH_HiDebug_StopAppTraceCapture()
173 {
174 return ConvertTraceErrorCode(OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().StopAppTraceCapture());
175 }
176
OH_HiDebug_GetGraphicsMemory(uint32_t * value)177 HiDebug_ErrorCode OH_HiDebug_GetGraphicsMemory(uint32_t *value)
178 {
179 if (value == nullptr) {
180 return HIDEBUG_INVALID_ARGUMENT;
181 }
182 std::optional<int32_t> ret = OHOS::HiviewDFX::HidebugNativeInterface::GetInstance().GetGraphicsMemory();
183 if (!ret || ret < 0) {
184 return HIDEBUG_TRACE_ABNORMAL;
185 }
186 *value = static_cast<uint32_t>(ret.value());
187 return HIDEBUG_SUCCESS;
188 }
189
OH_HiDebug_SetMallocDispatchTable(struct HiDebug_MallocDispatch * newDispatchTable)190 HiDebug_ErrorCode OH_HiDebug_SetMallocDispatchTable(struct HiDebug_MallocDispatch *newDispatchTable)
191 {
192 #ifdef HOOK_ENABLE
193 if (newDispatchTable == nullptr) {
194 return HIDEBUG_INVALID_ARGUMENT;
195 }
196 volatile struct MallocDispatchType *lastDispatchTable = (struct MallocDispatchType *)atomic_load_explicit(
197 &__musl_libc_globals.current_dispatch_table, memory_order_acquire);
198 if (lastDispatchTable != nullptr) {
199 g_lastDispatchTable = lastDispatchTable;
200 }
201 if (newDispatchTable->malloc != nullptr) {
202 g_currentDispatchDatable.malloc = newDispatchTable->malloc;
203 }
204 if (newDispatchTable->free != nullptr) {
205 g_currentDispatchDatable.free = newDispatchTable->free;
206 }
207 if (newDispatchTable->mmap != nullptr) {
208 g_currentDispatchDatable.mmap = newDispatchTable->mmap;
209 }
210 if (newDispatchTable->munmap != nullptr) {
211 g_currentDispatchDatable.munmap = newDispatchTable->munmap;
212 }
213 if (newDispatchTable->calloc != nullptr) {
214 g_currentDispatchDatable.calloc = newDispatchTable->calloc;
215 }
216 if (newDispatchTable->realloc != nullptr) {
217 g_currentDispatchDatable.realloc = newDispatchTable->realloc;
218 }
219 atomic_store_explicit(&__custom_hook_flag, (volatile bool)true, memory_order_seq_cst);
220 atomic_exchange_explicit(&__musl_libc_globals.current_dispatch_table,
221 (volatile const long long)&g_currentDispatchDatable, memory_order_acq_rel);
222 return HIDEBUG_SUCCESS;
223 #else
224 return HIDEBUG_INVALID_ARGUMENT;
225 #endif
226 }
227
OH_HiDebug_GetDefaultMallocDispatchTable(void)228 HiDebug_MallocDispatch* OH_HiDebug_GetDefaultMallocDispatchTable(void)
229 {
230 #ifdef HOOK_ENABLE
231 return &g_defaultDispatchDatable;
232 #else
233 return nullptr;
234 #endif
235 }
236
OH_HiDebug_RestoreMallocDispatchTable(void)237 void OH_HiDebug_RestoreMallocDispatchTable(void)
238 {
239 #ifdef HOOK_ENABLE
240 atomic_store_explicit(&__custom_hook_flag, (volatile bool)false, memory_order_seq_cst);
241 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)g_lastDispatchTable,
242 memory_order_seq_cst);
243 g_currentDispatchDatable = __libc_malloc_default_dispatch;
244 g_lastDispatchTable = nullptr;
245 #endif
246 }