• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
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 <atomic>
17 #include <climits>
18 #include <dlfcn.h>
19 #include <fcntl.h>
20 #include <malloc.h>
21 #include <string>
22 #include <sys/time.h>
23 #include <pthread.h>
24 #include <sys/prctl.h>
25 #include <unordered_map>
26 #include <unordered_set>
27 #include "dfx_regs_get.h"
28 #include "c/executor_task.h"
29 #include "common.h"
30 #include "hook_common.h"
31 #include "hook_socket_client.h"
32 #include "musl_preinit_common.h"
33 #include "parameter.h"
34 #include "stack_writer.h"
35 #include "runtime_stack_range.h"
36 #include "get_thread_id.h"
37 #include "hook_client.h"
38 #include <sys/mman.h>
39 #include "sampling.h"
40 #include "hitrace/trace.h"
41 
42 using namespace OHOS::HiviewDFX;
43 using namespace OHOS::Developtools::NativeDaemon;
44 
45 static pthread_key_t g_disableHookFlag;
46 static pthread_key_t g_hookTid;
47 static pthread_key_t g_updateThreadNameCount;
48 namespace {
49 static std::atomic<uint64_t> g_mallocTimes = 0;
50 
51 enum class MISC_TYPE : uint32_t {
52     JS_STACK_DATA = 1,
53 };
54 
55 #ifdef PERFORMANCE_DEBUG
56 static std::atomic<uint64_t> g_timeCost = 0;
57 static std::atomic<uint64_t> g_dataCounts = 0;
58 constexpr int PRINT_INTERVAL = 5000;
59 constexpr uint64_t S_TO_NS = 1000 * 1000 * 1000;
60 #endif
61 
62 using OHOS::Developtools::NativeDaemon::buildArchType;
63 static std::shared_ptr<HookSocketClient> g_hookClient {nullptr};
64 static Sampling g_sampler;
65 std::recursive_timed_mutex g_ClientMutex;
66 std::mutex g_tagMapMutex;
67 std::atomic<const MallocDispatchType*> g_dispatch {nullptr};
68 constexpr int UPDATE_THEARD_NAME = 1000;
69 static pid_t g_hookPid = 0;
70 static ClientConfig g_ClientConfig = {0};
71 static uint32_t g_maxSize = INT_MAX;
72 static std::unordered_map<std::string, uint32_t> g_memTagMap;
73 constexpr int PID_STR_SIZE = 4;
74 constexpr int STATUS_LINE_SIZE = 512;
75 constexpr int PID_NAMESPACE_ID = 1; // 1: pid is 1 after pid namespace used
76 constexpr int FD_PATH_LENGTH = 64;
77 constexpr int MIN_SAMPLER_INTERVAL = 1;
78 constexpr int FIRST_HASH = 16;
79 constexpr int SECOND_HASH = 13;
80 constexpr int THRESHOLD = 256;
81 constexpr int DIVIDE_VAL = 64;
82 //5: fp mode is used, response_library_mode maximum stack depth
83 #if defined(__aarch64__)
84 constexpr int RESPONSE_LIBRARY_MODE_DEPTH = 5;
85 constexpr int TEMP_IP = 100;
86 #endif
87 static bool g_isPidChanged = false;
88 static struct mallinfo2 g_miStart = {0};
89 std::vector<std::pair<uint64_t, uint64_t>> g_filterStaLibRange;
90 constexpr int MAX_BITPOOL_SIZE = 1000 * 1024;
91 struct Bitpool {
92     std::atomic<uint64_t> slot;
93 };
94 Bitpool* g_addressChecker = nullptr;
95 
AddrHash(uint32_t h)96 inline static uint32_t AddrHash(uint32_t h)
97 {
98     h ^= h >> FIRST_HASH;
99     h *= 0x85ebca6b;
100     h ^= h >> SECOND_HASH;
101     h *= 0xc2b2ae35;
102     h ^= h >> FIRST_HASH;
103     return h;
104 }
105 
Addr2Bitpool(void * addr)106 inline void Addr2Bitpool(void* addr)
107 {
108     if (!g_addressChecker) {
109         return;
110     }
111     uint32_t val = AddrHash(static_cast<uint32_t>(reinterpret_cast<uint64_t>(addr))) % (MAX_BITPOOL_SIZE * DIVIDE_VAL);
112     g_addressChecker[val / DIVIDE_VAL].slot |= (0x1 << (val % DIVIDE_VAL));
113 }
114 
IsAddrExist(void * addr)115 inline bool IsAddrExist(void* addr)
116 {
117     if (!g_addressChecker) {
118         return true;
119     }
120     uint32_t val = AddrHash(static_cast<uint32_t>(reinterpret_cast<uint64_t>(addr))) % (MAX_BITPOOL_SIZE * DIVIDE_VAL);
121     if (g_addressChecker[val / DIVIDE_VAL].slot.load() & (0x1 << (val % DIVIDE_VAL))) {
122         return true;
123     }
124     return false;
125 }
126 
GetDispatch()127 const MallocDispatchType* GetDispatch()
128 {
129     return g_dispatch.load(std::memory_order_relaxed);
130 }
131 
InititalizeIPC()132 bool InititalizeIPC()
133 {
134     return true;
135 }
FinalizeIPC()136 void FinalizeIPC() {}
137 
ConvertPid(char * buf)138 int ConvertPid(char* buf)
139 {
140     int count = 0;
141     char pidBuf[11] = {0}; /* 11: 32 bits to the maximum length of a string */
142     char *str = buf;
143     while (*str != '\0') {
144         if ((*str >= '0') && (*str <= '9') && (static_cast<unsigned long>(count) < sizeof(pidBuf) - 1)) {
145             pidBuf[count] = *str;
146             count++;
147             str++;
148             continue;
149         }
150 
151         if (count > 0) {
152             break;
153         }
154         str++;
155     }
156     return atoi(pidBuf);
157 }
158 
GetRealPid(void)159 pid_t GetRealPid(void)
160 {
161     const char *path = "/proc/self/status";
162     char buf[STATUS_LINE_SIZE] = {0};
163     FILE *fp = fopen(path, "r");
164     CHECK_NOTNULL(fp, -1, "fopen fail");
165     while (!feof(fp)) {
166         if (fgets(buf, STATUS_LINE_SIZE, fp) == nullptr) {
167             fclose(fp);
168             return -1;
169         }
170         if (strncmp(buf, "Pid:", PID_STR_SIZE) == 0) {
171             break;
172         }
173     }
174     (void)fclose(fp);
175     return static_cast<pid_t>(ConvertPid(buf));
176 }
177 }  // namespace
178 
GetCurThreadId()179 pid_t inline __attribute__((always_inline)) GetCurThreadId()
180 {
181     if (pthread_getspecific(g_hookTid) == nullptr) {
182         pthread_setspecific(g_hookTid, reinterpret_cast<void *>(GetThreadId()));
183     }
184     return reinterpret_cast<long>((pthread_getspecific(g_hookTid)));
185 }
186 
UpdateThreadName(std::shared_ptr<HookSocketClient> & client)187 bool inline __attribute__((always_inline)) UpdateThreadName(std::shared_ptr<HookSocketClient>& client)
188 {
189     long updateCount = reinterpret_cast<long>(pthread_getspecific(g_updateThreadNameCount));
190     bool ret = true;
191     if (updateCount == 0) {
192         StackRawData tnameData = {{{{0}}}};
193         tnameData.tid = static_cast<uint32_t>(GetCurThreadId());
194         tnameData.type = THREAD_NAME_MSG;
195         prctl(PR_GET_NAME, tnameData.name);
196         ret = client->SendStackWithPayload(&tnameData,
197                                            sizeof(BaseStackRawData) + strlen(tnameData.name) + 1, nullptr, 0);
198         if (!ret) {
199             return ret;
200         }
201     }
202     pthread_setspecific(g_updateThreadNameCount,
203                         reinterpret_cast<void *>(updateCount == UPDATE_THEARD_NAME ? 0 : updateCount + 1));
204     return ret;
205 }
206 
GetTagId(std::shared_ptr<HookSocketClient> & client,const char * tagName)207 uint32_t inline __attribute__((always_inline)) GetTagId(std::shared_ptr<HookSocketClient>& client, const char* tagName)
208 {
209     if (tagName == nullptr || strlen(tagName) > PATH_MAX) {
210         return 0;
211     }
212     uint32_t tagId = 0;
213     bool isNewTag = false;
214     std::unique_lock<std::mutex> lock(g_tagMapMutex);
215     auto it = g_memTagMap.find(tagName);
216     if (it == g_memTagMap.end()) {
217         isNewTag = true;
218         tagId = g_memTagMap.size() + 1;
219         g_memTagMap[tagName] = tagId;
220     } else {
221         tagId = it->second;
222     }
223     lock.unlock();
224     if (isNewTag) {
225         StackRawData tagData = {{{{0}}}};
226         tagData.type = MEMORY_TAG;
227         tagData.tagId = tagId;
228         strcpy_s(tagData.name, PATH_MAX + 1, tagName);
229         if (client != nullptr) {
230             client->SendStackWithPayload(&tagData, sizeof(BaseStackRawData) + strlen(tagName) + 1, nullptr, 0);
231         }
232     }
233     return tagId;
234 }
235 
236 static bool IsPidChanged(void);
237 
MallocHookStart(void * disableHookCallback)238 void* MallocHookStart(void* disableHookCallback)
239 {
240     std::lock_guard<std::recursive_timed_mutex> guard(g_ClientMutex);
241     g_addressChecker = new Bitpool [MAX_BITPOOL_SIZE] {{0}};
242     g_mallocTimes = 0;
243     g_hookClient.reset();
244     if (g_hookClient != nullptr) {
245         return nullptr;
246     } else {
247         g_ClientConfig.Reset();
248         g_sampler.Reset();
249         g_hookClient = std::make_shared<HookSocketClient>(g_hookPid, &g_ClientConfig, &g_sampler,
250                                                           reinterpret_cast<void (*)()>(disableHookCallback));
251     }
252     return nullptr;
253 }
254 
ohos_malloc_hook_on_start(void (* disableHookCallback)())255 bool ohos_malloc_hook_on_start(void (*disableHookCallback)())
256 {
257     pthread_t threadStart;
258     if (pthread_create(&threadStart, nullptr, MallocHookStart,
259                        reinterpret_cast<void *>(disableHookCallback))) {
260         return false;
261     }
262     pthread_detach(threadStart);
263     g_hookPid = GetRealPid();
264     pthread_key_create(&g_disableHookFlag, nullptr);
265     pthread_setspecific(g_disableHookFlag, nullptr);
266     pthread_key_create(&g_hookTid, nullptr);
267     pthread_setspecific(g_hookTid, nullptr);
268     pthread_key_create(&g_updateThreadNameCount, nullptr);
269     pthread_setspecific(g_updateThreadNameCount, reinterpret_cast<void *>(0));
270     GetMainThreadRuntimeStackRange(g_filterStaLibRange);
271     constexpr int paramBufferLen = 128;
272     char paramOutBuf[paramBufferLen] = {0};
273     int ret = GetParameter("persist.hiviewdfx.profiler.mem.filter", "", paramOutBuf, paramBufferLen);
274     if (ret > 0) {
275         int min = 0;
276         int max = 0;
277         if (sscanf_s(paramOutBuf, "%d,%d", &min, &max) == 2) { // 2: two parameters.
278             g_maxSize = max > 0 ? max : INT_MAX;
279             g_ClientConfig.filterSize = min > 0 ? min : 0;
280         }
281     }
282     return true;
283 }
284 
ohos_release_on_end(void *)285 void* ohos_release_on_end(void*)
286 {
287     std::lock_guard<std::recursive_timed_mutex> guard(g_ClientMutex);
288     delete [] g_addressChecker;
289     g_addressChecker = nullptr;
290     g_hookClient = nullptr;
291     pthread_key_delete(g_disableHookFlag);
292     pthread_key_delete(g_hookTid);
293     pthread_key_delete(g_updateThreadNameCount);
294     g_ClientConfig.Reset();
295     return nullptr;
296 }
297 
ohos_malloc_hook_on_end(void)298 bool ohos_malloc_hook_on_end(void)
299 {
300     {
301         std::lock_guard<std::recursive_timed_mutex> guard(g_ClientMutex);
302         if (g_hookClient != nullptr) {
303             if (g_hookClient->GetNmdType() == 1) {
304                 g_hookClient->SendNmdInfo();
305             }
306             g_hookClient->SendEndMsg();
307             g_hookClient->Flush();
308         }
309     }
310     pthread_t threadEnd;
311     if (pthread_create(&threadEnd, nullptr, ohos_release_on_end, nullptr)) {
312         return false;
313     }
314     pthread_detach(threadEnd);
315     return true;
316 }
317 
FilterStandardSoIp(uint64_t ip)318 bool FilterStandardSoIp(uint64_t ip)
319 {
320     for (auto [soBegin, soEnd_]: g_filterStaLibRange) {
321         if (ip >= soBegin && ip < soEnd_) {
322             return true;
323         }
324     }
325     return false;
326 }
327 
328 #if defined(__aarch64__)
FpUnwind(int maxDepth,uint64_t * ip,int stackSize,const char * startPtr,const char * endPtr)329 static int inline __attribute__((always_inline)) FpUnwind(int maxDepth, uint64_t* ip, int stackSize,
330                                                           const char* startPtr, const char* endPtr)
331 {
332     void** startfp = (void**)__builtin_frame_address(0);
333     void** fp = startfp;
334     int depth = 0;
335     int count = 0;
336     uint64_t tempIp = 0;
337     while (depth < maxDepth) {
338         if (fp < (void**)startPtr || (fp + 1) >= (void**)endPtr) {
339             break;
340         }
341         void** nextFp = (void**)*fp;
342         if (nextFp <= fp) {
343             break;
344         }
345         if (((nextFp - startfp) * sizeof(void*)) > static_cast<unsigned long>(stackSize)) {
346             break;
347         }
348         fp = nextFp;
349         tempIp = *(reinterpret_cast<unsigned long*>(fp + 1));
350         if (tempIp <= TEMP_IP) {
351             break;
352         }
353         if (g_ClientConfig.responseLibraryMode) {
354             if (++count >= RESPONSE_LIBRARY_MODE_DEPTH || !FilterStandardSoIp(tempIp)) {
355                 break;
356             }
357         } else {
358             ip[depth++] = tempIp;
359         }
360     }
361     if (g_ClientConfig.responseLibraryMode) {
362         ip[0] = tempIp;
363         depth = 1;
364     }
365     return depth;
366 }
367 
getJsChainId()368 uint64_t getJsChainId()
369 {
370     if (g_ClientConfig.arktsConfig.jsStackReport > 0) {
371             OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
372             if (hitraceId.IsValid()) {
373                 return hitraceId.GetChainId();
374             }
375     }
376     return 0;
377 }
378 #endif
379 
hook_malloc(void * (* fn)(size_t),size_t size)380 void* hook_malloc(void* (*fn)(size_t), size_t size)
381 {
382     void* ret = nullptr;
383     if (fn) {
384         ret = fn(size);
385     }
386     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
387         return ret;
388     }
389     if (!ohos_set_filter_size(size, ret)) {
390         return ret;
391     }
392 
393 #ifdef PERFORMANCE_DEBUG
394     struct timespec start = {};
395     clock_gettime(CLOCK_REALTIME, &start);
396 #endif
397 
398     if (g_ClientConfig.sampleInterval > MIN_SAMPLER_INTERVAL && g_sampler.StartSampling(size) == 0) {  //0 not sampling
399 #ifdef PERFORMANCE_DEBUG
400         g_mallocTimes++;
401         struct timespec end = {};
402         clock_gettime(CLOCK_REALTIME, &end);
403         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
404         if (g_mallocTimes % PRINT_INTERVAL == 0) {
405             PROFILER_LOG_ERROR(LOG_CORE,
406                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
407                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
408         }
409 #endif
410         return ret;
411     }
412 
413     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
414     auto holder = weakClient.lock();
415     if (holder == nullptr) {
416         return ret;
417     }
418     if (!UpdateThreadName(holder)) {
419         return ret;
420     }
421     StackRawData rawdata = {{{{0}}}};
422     const char* stackptr = nullptr;
423     const char* stackendptr = nullptr;
424     int stackSize = 0;
425     int fpStackDepth = 0;
426     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
427 
428     if (g_ClientConfig.fpunwind) {
429 #ifdef __aarch64__
430         void* stackAddr = nullptr;
431         size_t coroutineStackSize = 0;
432         if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
433             stackSize = static_cast<int>(coroutineStackSize);
434             stackptr = reinterpret_cast<const char*>(stackAddr);
435             stackendptr = stackptr + coroutineStackSize;
436         } else {
437             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
438             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
439             stackSize = stackendptr - stackptr;
440         }
441         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
442         stackSize = 0;
443         rawdata.jsChainId = getJsChainId();
444 #endif
445     } else {
446         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
447         GetLocalRegs(regs);
448         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
449         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
450         stackSize = stackendptr - stackptr;
451         if (stackendptr == nullptr) {
452             stackSize = 0;
453         }
454     }
455     rawdata.type = MALLOC_MSG;
456     rawdata.pid = static_cast<uint32_t>(g_hookPid);
457     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
458     rawdata.mallocSize = size;
459     rawdata.addr = ret;
460     if (g_ClientConfig.sampleInterval >= THRESHOLD) {
461         Addr2Bitpool(ret);
462     }
463     int realSize = 0;
464     if (g_ClientConfig.fpunwind) {
465         realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
466     } else {
467         realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
468     }
469     holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
470     g_mallocTimes++;
471 #ifdef PERFORMANCE_DEBUG
472     struct timespec end = {};
473     clock_gettime(CLOCK_REALTIME, &end);
474     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
475     g_dataCounts += stackSize;
476     if (g_mallocTimes % PRINT_INTERVAL == 0) {
477         PROFILER_LOG_ERROR(LOG_CORE,
478             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
479             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
480     }
481 #endif
482     return ret;
483 }
484 
hook_aligned_alloc(void * (* fn)(size_t,size_t),size_t align,size_t len)485 void* hook_aligned_alloc(void* (*fn)(size_t, size_t), size_t align, size_t len)
486 {
487     void* ret = nullptr;
488     if (fn) {
489         ret = fn(align, len);
490     }
491     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
492         return ret;
493     }
494     if (!ohos_set_filter_size(len, ret)) {
495         return ret;
496     }
497 
498 #ifdef PERFORMANCE_DEBUG
499     struct timespec start = {};
500     clock_gettime(CLOCK_REALTIME, &start);
501 #endif
502 
503     if (g_ClientConfig.sampleInterval > MIN_SAMPLER_INTERVAL && g_sampler.StartSampling(len) == 0) {  //0 not sampling
504 #ifdef PERFORMANCE_DEBUG
505         g_mallocTimes++;
506         struct timespec end = {};
507         clock_gettime(CLOCK_REALTIME, &end);
508         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
509         if (g_mallocTimes % PRINT_INTERVAL == 0) {
510             PROFILER_LOG_ERROR(LOG_CORE,
511                 "g_aligned_allocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %"
512                 PRIu64"\n", g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(),
513                 g_timeCost.load() / g_mallocTimes.load());
514         }
515 #endif
516         return ret;
517     }
518 
519     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
520     auto holder = weakClient.lock();
521     if (holder == nullptr) {
522         return ret;
523     }
524     if (!UpdateThreadName(holder)) {
525         return ret;
526     }
527     StackRawData rawdata = {{{{0}}}};
528     const char* stackptr = nullptr;
529     const char* stackendptr = nullptr;
530     int stackSize = 0;
531     int fpStackDepth = 0;
532     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
533 
534     if (g_ClientConfig.fpunwind) {
535 #ifdef __aarch64__
536         void* stackAddr = nullptr;
537         size_t coroutineStackSize = 0;
538         if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
539             stackSize = static_cast<int>(coroutineStackSize);
540             stackptr = reinterpret_cast<const char*>(stackAddr);
541             stackendptr = stackptr + coroutineStackSize;
542         } else {
543             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
544             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
545             stackSize = stackendptr - stackptr;
546         }
547         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
548         stackSize = 0;
549         rawdata.jsChainId = getJsChainId();
550 #endif
551     } else {
552         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
553         GetLocalRegs(regs);
554         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
555         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
556         stackSize = stackendptr - stackptr;
557         if (stackendptr == nullptr) {
558             stackSize = 0;
559         }
560     }
561     rawdata.type = MALLOC_MSG;
562     rawdata.pid = static_cast<uint32_t>(g_hookPid);
563     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
564     rawdata.mallocSize = len;
565     rawdata.addr = ret;
566     if (g_ClientConfig.sampleInterval >= THRESHOLD) {
567         Addr2Bitpool(ret);
568     }
569     int realSize = 0;
570     if (g_ClientConfig.fpunwind) {
571         realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
572     } else {
573         realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
574     }
575     holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
576     g_mallocTimes++;
577 #ifdef PERFORMANCE_DEBUG
578     struct timespec end = {};
579     clock_gettime(CLOCK_REALTIME, &end);
580     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
581     g_dataCounts += stackSize;
582     if (g_mallocTimes % PRINT_INTERVAL == 0) {
583         PROFILER_LOG_ERROR(LOG_CORE,
584             "g_aligned_allocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %"
585             PRIu64"\n", g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(),
586             g_timeCost.load() / g_mallocTimes.load());
587     }
588 #endif
589     return ret;
590 }
591 
hook_valloc(void * (* fn)(size_t),size_t size)592 void* hook_valloc(void* (*fn)(size_t), size_t size)
593 {
594     void* pRet = nullptr;
595     if (fn) {
596         pRet = fn(size);
597     }
598     return pRet;
599 }
600 
hook_calloc(void * (* fn)(size_t,size_t),size_t number,size_t size)601 void* hook_calloc(void* (*fn)(size_t, size_t), size_t number, size_t size)
602 {
603     void* pRet = nullptr;
604     if (fn) {
605         pRet = fn(number, size);
606     }
607     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
608         return pRet;
609     }
610     if (!ohos_set_filter_size(number * size, pRet)) {
611         return pRet;
612     }
613 
614 #ifdef PERFORMANCE_DEBUG
615     struct timespec start = {};
616     clock_gettime(CLOCK_REALTIME, &start);
617 #endif
618 
619     if (g_ClientConfig.sampleInterval > MIN_SAMPLER_INTERVAL && g_sampler.StartSampling(size * number) == 0) {
620 #ifdef PERFORMANCE_DEBUG
621         g_mallocTimes++;
622         struct timespec end = {};
623         clock_gettime(CLOCK_REALTIME, &end);
624         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
625         if (g_mallocTimes % PRINT_INTERVAL == 0) {
626             PROFILER_LOG_ERROR(LOG_CORE,
627                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
628                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
629         }
630 #endif
631         return pRet;
632     }
633     StackRawData rawdata = {{{{0}}}};
634     const char* stackptr = nullptr;
635     const char* stackendptr = nullptr;
636     int stackSize = 0;
637     int fpStackDepth = 0;
638     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
639 
640     if (g_ClientConfig.fpunwind) {
641 #ifdef __aarch64__
642         void* stackAddr = nullptr;
643         size_t coroutineStackSize = 0;
644         if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
645             stackSize = static_cast<int>(coroutineStackSize);
646             stackptr = reinterpret_cast<const char*>(stackAddr);
647             stackendptr = stackptr + coroutineStackSize;
648         } else {
649             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
650             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
651             stackSize = stackendptr - stackptr;
652         }
653         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
654         stackSize = 0;
655         rawdata.jsChainId = getJsChainId();
656 #endif
657     } else {
658         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
659         GetLocalRegs(regs);
660         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
661         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
662         stackSize = stackendptr - stackptr;
663         if (stackendptr == nullptr) {
664             stackSize = 0;
665         }
666     }
667 
668     rawdata.type = MALLOC_MSG;
669     rawdata.pid = static_cast<uint32_t>(g_hookPid);
670     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
671     rawdata.mallocSize = number * size;
672     rawdata.addr = pRet;
673     if (g_ClientConfig.sampleInterval >= THRESHOLD) {
674         Addr2Bitpool(pRet);
675     }
676     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
677     auto holder = weakClient.lock();
678     if (holder != nullptr) {
679         int realSize = 0;
680         if (g_ClientConfig.fpunwind) {
681             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
682         } else {
683             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
684         }
685         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
686     }
687     g_mallocTimes++;
688 #ifdef PERFORMANCE_DEBUG
689     struct timespec end = {};
690     clock_gettime(CLOCK_REALTIME, &end);
691     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
692     if (g_mallocTimes % PRINT_INTERVAL == 0) {
693         PROFILER_LOG_ERROR(LOG_CORE,
694             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
695             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
696     }
697 #endif
698     return pRet;
699 }
700 
hook_memalign(void * (* fn)(size_t,size_t),size_t align,size_t bytes)701 void* hook_memalign(void* (*fn)(size_t, size_t), size_t align, size_t bytes)
702 {
703     void* pRet = nullptr;
704     if (fn) {
705         pRet = fn(align, bytes);
706     }
707     return pRet;
708 }
709 
hook_realloc(void * (* fn)(void *,size_t),void * ptr,size_t size)710 void* hook_realloc(void* (*fn)(void*, size_t), void* ptr, size_t size)
711 {
712     void* pRet = nullptr;
713     if (fn) {
714         pRet = fn(ptr, size);
715     }
716     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
717         return pRet;
718     }
719     if (!ohos_set_filter_size(size, pRet)) {
720         return pRet;
721     }
722 
723 #ifdef PERFORMANCE_DEBUG
724     struct timespec start = {};
725     clock_gettime(CLOCK_REALTIME, &start);
726 #endif
727 
728     if (g_ClientConfig.sampleInterval > MIN_SAMPLER_INTERVAL && g_sampler.StartSampling(size) == 0) {
729 #ifdef PERFORMANCE_DEBUG
730         g_mallocTimes++;
731         struct timespec end = {};
732         clock_gettime(CLOCK_REALTIME, &end);
733         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
734         if (g_mallocTimes % PRINT_INTERVAL == 0) {
735             PROFILER_LOG_ERROR(LOG_CORE,
736                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
737                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
738         }
739 #endif
740         return pRet;
741     }
742     StackRawData rawdata = {{{{0}}}};
743     StackRawData freeData = {{{{0}}}};
744     const char* stackptr = nullptr;
745     const char* stackendptr = nullptr;
746     int stackSize = 0;
747     int fpStackDepth = 0;
748     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
749 
750     if (g_ClientConfig.fpunwind) {
751 #ifdef __aarch64__
752         void* stackAddr = nullptr;
753         size_t coroutineStackSize = 0;
754         if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
755             stackSize = static_cast<int>(coroutineStackSize);
756             stackptr = reinterpret_cast<const char*>(stackAddr);
757             stackendptr = stackptr + coroutineStackSize;
758         } else {
759             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
760             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
761             stackSize = stackendptr - stackptr;
762         }
763         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
764         stackSize = 0;
765         if (g_ClientConfig.freeStackData) {
766             (void)memcpy_s(freeData.ip, sizeof(freeData.ip) / sizeof(uint64_t),
767                            rawdata.ip, sizeof(rawdata.ip) / sizeof(uint64_t));
768         }
769 #endif
770     } else {
771         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
772         GetLocalRegs(regs);
773         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
774         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
775         stackSize = stackendptr - stackptr;
776         if (stackendptr == nullptr) {
777             stackSize = 0;
778         }
779         if (g_ClientConfig.freeStackData) {
780             (void)memcpy_s(freeData.regs, sizeof(freeData.regs) / sizeof(char),
781                            rawdata.regs, sizeof(rawdata.regs) / sizeof(char));
782         }
783     }
784 
785     rawdata.type = MALLOC_MSG;
786     rawdata.pid = static_cast<uint32_t>(g_hookPid);
787     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
788     rawdata.mallocSize = size;
789     rawdata.addr = pRet;
790     if (g_ClientConfig.sampleInterval >= THRESHOLD) {
791         Addr2Bitpool(pRet);
792     }
793     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
794     auto holder = weakClient.lock();
795     if (holder != nullptr) {
796         int realSize = 0;
797         int freeRealSize = 0;
798         freeData.type = FREE_MSG;
799         freeData.pid = rawdata.pid;
800         freeData.tid = rawdata.tid;
801         freeData.mallocSize = 0;
802         freeData.addr = ptr;
803         freeData.ts = rawdata.ts;
804         if (g_ClientConfig.fpunwind) {
805             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
806             freeRealSize = sizeof(BaseStackRawData);
807         } else {
808             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
809             freeRealSize = realSize;
810         }
811         holder->SendStackWithPayload(&freeData, freeRealSize, nullptr, 0); // 0: Don't unwind the freeData
812         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
813     }
814 #ifdef PERFORMANCE_DEBUG
815     g_mallocTimes++;
816     struct timespec end = {};
817     clock_gettime(CLOCK_REALTIME, &end);
818     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
819     if (g_mallocTimes % PRINT_INTERVAL == 0) {
820         PROFILER_LOG_ERROR(LOG_CORE,
821             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
822             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
823     }
824 #endif
825     return pRet;
826 }
827 
hook_malloc_usable_size(size_t (* fn)(void *),void * ptr)828 size_t hook_malloc_usable_size(size_t (*fn)(void*), void* ptr)
829 {
830     size_t ret = 0;
831     if (fn) {
832         ret = fn(ptr);
833     }
834 
835     return ret;
836 }
837 
hook_free(void (* free_func)(void *),void * p)838 void hook_free(void (*free_func)(void*), void* p)
839 {
840     if (g_ClientConfig.statisticsInterval > 0) {
841         if (!free_func) {
842             return;
843         }
844         if (g_ClientConfig.mallocDisable || IsPidChanged()) {
845             free_func(p);
846             return;
847         }
848         std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
849         auto holder = weakClient.lock();
850         if ((holder != nullptr) && p) {
851             holder->SendStackWithPayload(&p, sizeof(void*), nullptr, 0);
852         }
853         free_func(p);
854 #ifdef PERFORMANCE_DEBUG
855         g_mallocTimes++;
856         struct timespec end = {};
857         clock_gettime(CLOCK_REALTIME, &end);
858         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
859         if (g_mallocTimes % PRINT_INTERVAL == 0) {
860             PROFILER_LOG_ERROR(LOG_CORE,
861                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
862                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
863         }
864 #endif
865         return;
866     }
867     struct timespec freeTime = {};
868     clock_gettime(g_ClientConfig.clockId, &freeTime);
869     if (free_func) {
870         free_func(p);
871     }
872     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
873         return;
874     }
875     if (g_ClientConfig.sampleInterval >= THRESHOLD) {
876         if (!IsAddrExist(p)) {
877             return;
878         }
879     }
880 #ifdef PERFORMANCE_DEBUG
881     struct timespec start = {};
882     clock_gettime(CLOCK_REALTIME, &start);
883 #endif
884 
885     StackRawData rawdata = {{{{0}}}};
886     const char* stackptr = nullptr;
887     const char* stackendptr = nullptr;
888     int stackSize = 0;
889     int fpStackDepth = 0;
890     rawdata.ts = freeTime;
891 
892     if (g_ClientConfig.freeStackData) {
893         if (g_ClientConfig.fpunwind) {
894 #ifdef __aarch64__
895             void* stackAddr = nullptr;
896             size_t coroutineStackSize = 0;
897             if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
898                 stackSize = static_cast<int>(coroutineStackSize);
899                 stackptr = reinterpret_cast<const char*>(stackAddr);
900                 stackendptr = stackptr + coroutineStackSize;
901             } else {
902                 stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
903                 GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
904                 stackSize = stackendptr - stackptr;
905             }
906             fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
907             stackSize = 0;
908             rawdata.jsChainId = getJsChainId();
909 #endif
910         } else {
911             unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
912             GetLocalRegs(regs);
913             stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
914             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
915             stackSize = stackendptr - stackptr;
916             if (stackendptr == nullptr) {
917                 stackSize = 0;
918             }
919         }
920     }
921 
922     rawdata.type = FREE_MSG;
923     rawdata.pid = static_cast<uint32_t>(g_hookPid);
924     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
925     rawdata.mallocSize = 0;
926     rawdata.addr = p;
927     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
928     auto holder = weakClient.lock();
929     if (holder != nullptr) {
930         int realSize = 0;
931         if (g_ClientConfig.fpunwind) {
932             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
933         } else {
934             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
935         }
936         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
937     }
938 #ifdef PERFORMANCE_DEBUG
939         g_mallocTimes++;
940         struct timespec end = {};
941         clock_gettime(CLOCK_REALTIME, &end);
942         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
943         if (g_mallocTimes % PRINT_INTERVAL == 0) {
944             PROFILER_LOG_ERROR(LOG_CORE,
945                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
946                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
947         }
948 #endif
949 }
950 
SendMmapFileRawData(int prot,int flags,off_t offset,const std::string & filePath,const StackRawData & rawdata,std::shared_ptr<HookSocketClient> & holder)951 inline void SendMmapFileRawData(int prot, int flags, off_t offset, const std::string& filePath,
952                                 const StackRawData& rawdata, std::shared_ptr<HookSocketClient>& holder)
953 {
954     StackRawData curRawdata = {{{{0}}}};
955     curRawdata.addr = rawdata.addr;
956     curRawdata.pid = static_cast<uint32_t>(g_hookPid);
957     curRawdata.mallocSize = rawdata.mallocSize;
958     curRawdata.mmapArgs.offset = offset;
959     curRawdata.type = OHOS::Developtools::NativeDaemon::MMAP_FILE_TYPE;
960     if (prot & PROT_EXEC) {
961         curRawdata.mmapArgs.flags |= PROT_EXEC;
962     }
963     size_t len = strlen(filePath.c_str()) + 1;
964     if (strncpy_s(curRawdata.name, PATH_MAX + 1, filePath.c_str(), len) != EOK) {
965         return;
966     }
967     if (flags & MAP_FIXED) {
968         curRawdata.mmapArgs.flags |= MAP_FIXED;
969     }
970     holder->SendStackWithPayload(&curRawdata, sizeof(BaseStackRawData) + len, nullptr, 0);
971 }
972 
hook_mmap(void * (* fn)(void *,size_t,int,int,int,off_t),void * addr,size_t length,int prot,int flags,int fd,off_t offset)973 void* hook_mmap(void*(*fn)(void*, size_t, int, int, int, off_t),
974     void* addr, size_t length, int prot, int flags, int fd, off_t offset)
975 {
976     void* ret = nullptr;
977     if (fn) {
978         ret = fn(addr, length, prot, flags, fd, offset);
979     }
980     if (g_ClientConfig.mmapDisable || IsPidChanged()) {
981         return ret;
982     }
983 
984 #ifdef PERFORMANCE_DEBUG
985     struct timespec start = {};
986     clock_gettime(CLOCK_REALTIME, &start);
987 #endif
988 
989     if ((fd < 0 && offset == 0) && g_ClientConfig.sampleInterval > MIN_SAMPLER_INTERVAL
990         && g_sampler.StartSampling(length) == 0) {
991 #ifdef PERFORMANCE_DEBUG
992         g_mallocTimes++;
993         struct timespec end = {};
994         clock_gettime(CLOCK_REALTIME, &end);
995         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
996         if (g_mallocTimes % PRINT_INTERVAL == 0) {
997             PROFILER_LOG_ERROR(LOG_CORE,
998                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
999                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
1000         }
1001 #endif
1002         return ret;
1003     }
1004     StackRawData rawdata = {{{{0}}}};
1005     const char* stackptr = nullptr;
1006     const char* stackendptr = nullptr;
1007     int stackSize = 0;
1008     int fpStackDepth = 0;
1009     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
1010 
1011     if (g_ClientConfig.fpunwind) {
1012 #ifdef __aarch64__
1013         void* stackAddr = nullptr;
1014         size_t coroutineStackSize = 0;
1015         if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
1016             stackSize = static_cast<int>(coroutineStackSize);
1017             stackptr = reinterpret_cast<const char*>(stackAddr);
1018             stackendptr = stackptr + coroutineStackSize;
1019         } else {
1020             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
1021             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
1022             stackSize = stackendptr - stackptr;
1023         }
1024         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
1025         stackSize = 0;
1026         rawdata.jsChainId = getJsChainId();
1027 #endif
1028     } else {
1029         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
1030         GetLocalRegs(regs);
1031         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
1032         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
1033         stackSize = stackendptr - stackptr;
1034         if (stackendptr == nullptr) {
1035             stackSize = 0;
1036         }
1037     }
1038 
1039     rawdata.type = MMAP_MSG;
1040     rawdata.pid = static_cast<uint32_t>(g_hookPid);
1041     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
1042     rawdata.mallocSize = length;
1043     rawdata.addr = ret;
1044     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
1045     auto holder = weakClient.lock();
1046     if (holder == nullptr) {
1047         return ret;
1048     }
1049     if (fd >= 0) {
1050         rawdata.type = MMAP_FILE_PAGE_MSG;
1051         char path[FD_PATH_LENGTH] = {0};
1052         char fileName[PATH_MAX + 1] = {0};
1053         (void)snprintf_s(path, FD_PATH_LENGTH, FD_PATH_LENGTH - 1, "/proc/self/fd/%d", fd);
1054         ssize_t len = readlink(path, fileName, sizeof(fileName) - 1);
1055         if (len != -1) {
1056             fileName[len] = '\0';
1057             SendMmapFileRawData(prot, flags, offset, fileName, rawdata, holder);
1058             char* p = strrchr(fileName, '/');
1059             if (p != nullptr) {
1060                 rawdata.tagId = GetTagId(holder, &fileName[p - fileName + 1]);
1061             } else {
1062                 rawdata.tagId = GetTagId(holder, fileName);
1063             }
1064         }
1065     }
1066     if (!UpdateThreadName(holder)) {
1067         return ret;
1068     }
1069     int realSize = 0;
1070     if (g_ClientConfig.fpunwind) {
1071         realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
1072     } else {
1073         realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
1074     }
1075     holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
1076 #ifdef PERFORMANCE_DEBUG
1077     g_mallocTimes++;
1078     struct timespec end = {};
1079     clock_gettime(CLOCK_REALTIME, &end);
1080     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
1081     if (g_mallocTimes % PRINT_INTERVAL == 0) {
1082         PROFILER_LOG_ERROR(LOG_CORE,
1083             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
1084             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
1085     }
1086 #endif
1087     return ret;
1088 }
1089 
hook_munmap(int (* fn)(void *,size_t),void * addr,size_t length)1090 int hook_munmap(int(*fn)(void*, size_t), void* addr, size_t length)
1091 {
1092     int ret = -1;
1093     struct timespec unmapTime = {};
1094     clock_gettime(g_ClientConfig.clockId, &unmapTime);
1095     if (fn) {
1096         ret = fn(addr, length);
1097     }
1098     if (g_ClientConfig.mmapDisable || IsPidChanged()) {
1099         return ret;
1100     }
1101 
1102 #ifdef PERFORMANCE_DEBUG
1103     struct timespec start = {};
1104     clock_gettime(CLOCK_REALTIME, &start);
1105 #endif
1106 
1107     int stackSize = 0;
1108     StackRawData rawdata = {{{{0}}}};
1109     const char* stackptr = nullptr;
1110     const char* stackendptr = nullptr;
1111     int fpStackDepth = 0;
1112     rawdata.ts = unmapTime;
1113     if (g_ClientConfig.munmapStackData) {
1114         if (g_ClientConfig.fpunwind) {
1115 #ifdef __aarch64__
1116             void* stackAddr = nullptr;
1117             size_t coroutineStackSize = 0;
1118             if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
1119                 stackSize = static_cast<int>(coroutineStackSize);
1120                 stackptr = reinterpret_cast<const char*>(stackAddr);
1121                 stackendptr = stackptr + coroutineStackSize;
1122             } else {
1123                 stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
1124                 GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
1125                 stackSize = stackendptr - stackptr;
1126             }
1127             fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
1128             stackSize = 0;
1129             rawdata.jsChainId = getJsChainId();
1130 #endif
1131         } else {
1132             unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
1133             GetLocalRegs(regs);
1134             stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
1135             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
1136             stackSize = stackendptr - stackptr;
1137             if (stackendptr == nullptr) {
1138                 stackSize = 0;
1139             }
1140         }
1141     }
1142 
1143     rawdata.type = MUNMAP_MSG;
1144     rawdata.pid = static_cast<uint32_t>(g_hookPid);
1145     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
1146     rawdata.mallocSize = length;
1147     rawdata.addr = addr;
1148     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
1149     auto holder = weakClient.lock();
1150     if (holder != nullptr) {
1151         int realSize = 0;
1152         if (g_ClientConfig.fpunwind) {
1153             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
1154         } else {
1155             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
1156         }
1157         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
1158     }
1159 #ifdef PERFORMANCE_DEBUG
1160     g_mallocTimes++;
1161     struct timespec end = {};
1162     clock_gettime(CLOCK_REALTIME, &end);
1163     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
1164     if (g_mallocTimes % PRINT_INTERVAL == 0) {
1165         PROFILER_LOG_ERROR(LOG_CORE,
1166             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
1167             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
1168     }
1169 #endif
1170     return ret;
1171 }
1172 
hook_prctl(int (* fn)(int,...),int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5)1173 int hook_prctl(int(*fn)(int, ...),
1174     int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
1175 {
1176     int ret = -1;
1177     if (fn) {
1178         ret = fn(option, arg2, arg3, arg4, arg5);
1179     }
1180     if (reinterpret_cast<char*>(arg5) == nullptr || IsPidChanged()) {
1181         return ret;
1182     }
1183     if (option == PR_SET_VMA && arg2 == PR_SET_VMA_ANON_NAME) {
1184 #ifdef PERFORMANCE_DEBUG
1185         struct timespec start = {};
1186         clock_gettime(CLOCK_REALTIME, &start);
1187 #endif
1188         StackRawData rawdata = {{{{0}}}};
1189         clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
1190         rawdata.type = PR_SET_VMA_MSG;
1191         rawdata.pid = static_cast<uint32_t>(g_hookPid);
1192         rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
1193         rawdata.mallocSize = arg4;
1194         rawdata.addr = reinterpret_cast<void*>(arg3);
1195         size_t tagLen = strlen(reinterpret_cast<char*>(arg5)) + 1;
1196         if (memcpy_s(rawdata.name, sizeof(rawdata.name), reinterpret_cast<char*>(arg5), tagLen) != EOK) {
1197             HILOG_ERROR(LOG_CORE, "memcpy_s tag failed");
1198         }
1199         rawdata.name[sizeof(rawdata.name) - 1] = '\0';
1200         std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
1201         auto holder = weakClient.lock();
1202         if (holder != nullptr) {
1203             holder->SendStackWithPayload(&rawdata, sizeof(BaseStackRawData) + tagLen, nullptr, 0);
1204         }
1205 #ifdef PERFORMANCE_DEBUG
1206         g_mallocTimes++;
1207         struct timespec end = {};
1208         clock_gettime(CLOCK_REALTIME, &end);
1209         g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
1210         if (g_mallocTimes % PRINT_INTERVAL == 0) {
1211             PROFILER_LOG_ERROR(LOG_CORE,
1212                 "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
1213                 g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
1214         }
1215 #endif
1216     }
1217     return ret;
1218 }
1219 
hook_memtrace(void * addr,size_t size,const char * tag,bool isUsing)1220 void hook_memtrace(void* addr, size_t size, const char* tag, bool isUsing)
1221 {
1222     if (!g_ClientConfig.memtraceEnable || IsPidChanged()) {
1223         return;
1224     }
1225 #ifdef PERFORMANCE_DEBUG
1226     struct timespec start = {};
1227     clock_gettime(CLOCK_REALTIME, &start);
1228 #endif
1229     int stackSize = 0;
1230     StackRawData rawdata = {{{{0}}}};
1231     const char* stackptr = nullptr;
1232     const char* stackendptr = nullptr;
1233     int fpStackDepth = 0;
1234     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
1235 
1236     if (isUsing) {
1237         if (g_ClientConfig.fpunwind) {
1238 #ifdef __aarch64__
1239             void* stackAddr = nullptr;
1240             size_t coroutineStackSize = 0;
1241             if (ffrt_get_current_coroutine_stack(&stackAddr, &coroutineStackSize)) {
1242                 stackSize = static_cast<int>(coroutineStackSize);
1243                 stackptr = reinterpret_cast<const char*>(stackAddr);
1244                 stackendptr = stackptr + coroutineStackSize;
1245             } else {
1246                 stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
1247                 GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
1248                 stackSize = stackendptr - stackptr;
1249             }
1250             fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize, stackptr, stackendptr);
1251             stackSize = 0;
1252             rawdata.jsChainId = getJsChainId();
1253 #endif
1254         } else {
1255             unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
1256             GetLocalRegs(regs);
1257             stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
1258             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
1259             stackSize = stackendptr - stackptr;
1260             if (stackendptr == nullptr) {
1261                 stackSize = 0;
1262             }
1263         }
1264     }
1265     rawdata.type = isUsing ? MEMORY_USING_MSG : MEMORY_UNUSING_MSG;
1266     rawdata.pid = static_cast<uint32_t>(g_hookPid);
1267     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
1268     rawdata.mallocSize = size;
1269     rawdata.addr = addr;
1270     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
1271     auto holder = weakClient.lock();
1272     rawdata.tagId = isUsing ? GetTagId(holder, tag) : 0;
1273     if (holder != nullptr) {
1274         int realSize = 0;
1275         if (g_ClientConfig.fpunwind) {
1276             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
1277         } else {
1278             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
1279         }
1280         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
1281     }
1282 #ifdef PERFORMANCE_DEBUG
1283     g_mallocTimes++;
1284     struct timespec end = {};
1285     clock_gettime(CLOCK_REALTIME, &end);
1286     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
1287     if (g_mallocTimes % PRINT_INTERVAL == 0) {
1288         PROFILER_LOG_ERROR(LOG_CORE,
1289             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
1290             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
1291     }
1292 #endif
1293 }
1294 
ohos_malloc_hook_initialize(const MallocDispatchType * malloc_dispatch,bool *,const char *)1295 bool ohos_malloc_hook_initialize(const MallocDispatchType*malloc_dispatch, bool*, const char*)
1296 {
1297     g_dispatch.store(malloc_dispatch);
1298     InititalizeIPC();
1299     return true;
1300 }
ohos_malloc_hook_finalize(void)1301 void ohos_malloc_hook_finalize(void)
1302 {
1303     FinalizeIPC();
1304 }
1305 
ohos_malloc_hook_malloc(size_t size)1306 void* ohos_malloc_hook_malloc(size_t size)
1307 {
1308     __set_hook_flag(false);
1309     void* ret = hook_malloc(GetDispatch()->malloc, size);
1310     __set_hook_flag(true);
1311     return ret;
1312 }
1313 
ohos_malloc_hook_realloc(void * ptr,size_t size)1314 void* ohos_malloc_hook_realloc(void* ptr, size_t size)
1315 {
1316     __set_hook_flag(false);
1317     void* ret = hook_realloc(GetDispatch()->realloc, ptr, size);
1318     __set_hook_flag(true);
1319     return ret;
1320 }
1321 
ohos_malloc_hook_calloc(size_t number,size_t size)1322 void* ohos_malloc_hook_calloc(size_t number, size_t size)
1323 {
1324     __set_hook_flag(false);
1325     void* ret = hook_calloc(GetDispatch()->calloc, number, size);
1326     __set_hook_flag(true);
1327     return ret;
1328 }
1329 
ohos_malloc_hook_valloc(size_t size)1330 void* ohos_malloc_hook_valloc(size_t size)
1331 {
1332     __set_hook_flag(false);
1333     void* ret = hook_valloc(GetDispatch()->valloc, size);
1334     __set_hook_flag(true);
1335     return ret;
1336 }
1337 
ohos_malloc_hook_free(void * p)1338 void ohos_malloc_hook_free(void* p)
1339 {
1340     __set_hook_flag(false);
1341     hook_free(GetDispatch()->free, p);
1342     __set_hook_flag(true);
1343 }
1344 
ohos_malloc_hook_malloc_usable_size(void * mem)1345 size_t ohos_malloc_hook_malloc_usable_size(void* mem)
1346 {
1347     __set_hook_flag(false);
1348     size_t ret = hook_malloc_usable_size(GetDispatch()->malloc_usable_size, mem);
1349     __set_hook_flag(true);
1350     return ret;
1351 }
1352 
ohos_malloc_hook_get_hook_flag(void)1353 bool ohos_malloc_hook_get_hook_flag(void)
1354 {
1355     return pthread_getspecific(g_disableHookFlag) == nullptr;
1356 }
1357 
ohos_malloc_hook_set_hook_flag(bool flag)1358 bool ohos_malloc_hook_set_hook_flag(bool flag)
1359 {
1360     bool oldFlag = ohos_malloc_hook_get_hook_flag();
1361     if (flag) {
1362         pthread_setspecific(g_disableHookFlag, nullptr);
1363     } else {
1364         pthread_setspecific(g_disableHookFlag, reinterpret_cast<void *>(1));
1365     }
1366     return oldFlag;
1367 }
1368 
ohos_malloc_hook_mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)1369 void* ohos_malloc_hook_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset)
1370 {
1371     __set_hook_flag(false);
1372     void* ret = hook_mmap(GetDispatch()->mmap, addr, length, prot, flags, fd, offset);
1373     __set_hook_flag(true);
1374     return ret;
1375 }
1376 
ohos_malloc_hook_munmap(void * addr,size_t length)1377 int ohos_malloc_hook_munmap(void* addr, size_t length)
1378 {
1379     __set_hook_flag(false);
1380     int ret = hook_munmap(GetDispatch()->munmap, addr, length);
1381     __set_hook_flag(true);
1382     return ret;
1383 }
1384 
ohos_malloc_hook_memtrace(void * addr,size_t size,const char * tag,bool isUsing)1385 void ohos_malloc_hook_memtrace(void* addr, size_t size, const char* tag, bool isUsing)
1386 {
1387     __set_hook_flag(false);
1388     hook_memtrace(addr, size, tag, isUsing);
1389     __set_hook_flag(true);
1390 }
1391 
ohos_malloc_hook_aligned_alloc(size_t align,size_t len)1392 void* ohos_malloc_hook_aligned_alloc(size_t align, size_t len)
1393 {
1394     __set_hook_flag(false);
1395     void* ret = hook_aligned_alloc(GetDispatch()->aligned_alloc, align, len);
1396     __set_hook_flag(true);
1397     return ret;
1398 }
1399 
ohos_malloc_hook_prctl(int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5)1400 int  ohos_malloc_hook_prctl(int option, unsigned long arg2, unsigned long arg3,
1401                             unsigned long arg4, unsigned long arg5)
1402 {
1403     __set_hook_flag(false);
1404     int ret = hook_prctl((GetDispatch()->prctl), option, arg2, arg3, arg4, arg5);
1405     __set_hook_flag(true);
1406     return ret;
1407 }
1408 
ohos_set_filter_size(size_t size,void * ret)1409 bool ohos_set_filter_size(size_t size, void* ret)
1410 {
1411     if (g_ClientConfig.filterSize < 0 || size < static_cast<size_t>(g_ClientConfig.filterSize) || size > g_maxSize) {
1412         return false;
1413     }
1414     return true;
1415 }
1416 
IsPidChanged(void)1417 static bool IsPidChanged(void)
1418 {
1419     if (g_isPidChanged) {
1420         return true;
1421     }
1422     int pid = getprocpid();
1423     // hap app after pid namespace used
1424     if (pid == PID_NAMESPACE_ID) {
1425         return false;
1426     } else {
1427         // native app & sa service
1428         g_isPidChanged = (g_hookPid != pid);
1429     }
1430     return g_isPidChanged;
1431 }
1432 
ohos_malloc_hook_send_hook_misc_data(uint64_t id,const char * stackPtr,size_t stackSize,uint32_t type)1433 bool ohos_malloc_hook_send_hook_misc_data(uint64_t id, const char* stackPtr, size_t stackSize, uint32_t type)
1434 {
1435     if (type == static_cast<uint32_t>(MISC_TYPE::JS_STACK_DATA)) {
1436         StackRawData rawdata = {{{{0}}}};
1437         rawdata.jsChainId = id;
1438         rawdata.type = JS_STACK_MSG;
1439         std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
1440         auto holder = weakClient.lock();
1441         if (holder != nullptr) {
1442             return holder->SendStackWithPayload(&rawdata, sizeof(BaseStackRawData), stackPtr, stackSize);
1443         }
1444     }
1445     return false;
1446 }
1447 
ohos_malloc_hook_get_hook_config()1448 void* ohos_malloc_hook_get_hook_config()
1449 {
1450     return &g_ClientConfig.arktsConfig;
1451 }