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