• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <atomic>
17 #include <climits>
18 #include <dlfcn.h>
19 #include <fcntl.h>
20 #include <string>
21 #include <sys/time.h>
22 #include <pthread.h>
23 #include <sys/prctl.h>
24 #include <unordered_map>
25 #include <unordered_set>
26 #include "common.h"
27 #include "hook_common.h"
28 #include "hook_socket_client.h"
29 #include "musl_preinit_common.h"
30 #include "parameter.h"
31 #include "stack_writer.h"
32 #include "runtime_stack_range.h"
33 #include "get_thread_id.h"
34 #include "hook_client.h"
35 #include <sys/mman.h>
36 
37 static pthread_key_t g_disableHookFlag;
38 static pthread_key_t g_hookTid;
39 static pthread_key_t g_updateThreadNameCount;
40 namespace {
41 static std::atomic<uint64_t> g_timeCost = 0;
42 static std::atomic<uint64_t> g_mallocTimes = 0;
43 static std::atomic<uint64_t> g_dataCounts = 0;
44 using OHOS::Developtools::NativeDaemon::buildArchType;
45 static std::shared_ptr<HookSocketClient> g_hookClient;
46 std::recursive_timed_mutex g_ClientMutex;
47 std::mutex g_tagMapMutex;
48 std::atomic<const MallocDispatchType*> g_dispatch {nullptr};
49 constexpr int TIMEOUT_MSEC = 2000;
50 constexpr int PRINT_INTERVAL = 5000;
51 constexpr int UPDATE_THEARD_NAME = 1000;
52 constexpr uint64_t S_TO_NS = 1000 * 1000 * 1000;
53 static pid_t g_hookPid = 0;
54 static ClientConfig g_ClientConfig = {0};
55 static uint32_t g_maxSize = INT_MAX;
56 static std::unordered_map<std::string, uint32_t> g_memTagMap;
57 constexpr int PID_STR_SIZE = 4;
58 constexpr int STATUS_LINE_SIZE = 512;
59 constexpr int PID_NAMESPACE_ID = 1; // 1: pid is 1 after pid namespace used
60 constexpr int FD_PATH_LENGTH = 64;
61 static bool g_isPidChanged = false;
GetDispatch()62 const MallocDispatchType* GetDispatch()
63 {
64     return g_dispatch.load(std::memory_order_relaxed);
65 }
66 
InititalizeIPC()67 bool InititalizeIPC()
68 {
69     return true;
70 }
FinalizeIPC()71 void FinalizeIPC() {}
72 
ConvertPid(char * buf)73 int ConvertPid(char* buf)
74 {
75     int count = 0;
76     char pidBuf[11] = {0}; /* 11: 32 bits to the maximum length of a string */
77     char *str = buf;
78     while (*str != '\0') {
79         if ((*str >= '0') && (*str <= '9') && (static_cast<unsigned long>(count) < sizeof(pidBuf) - 1)) {
80             pidBuf[count] = *str;
81             count++;
82             str++;
83             continue;
84         }
85 
86         if (count > 0) {
87             break;
88         }
89         str++;
90     }
91     return atoi(pidBuf);
92 }
93 
GetRealPid(void)94 pid_t GetRealPid(void)
95 {
96     const char *path = "/proc/self/status";
97     char buf[STATUS_LINE_SIZE] = {0};
98     FILE *fp = fopen(path, "r");
99     CHECK_NOTNULL(fp, -1, "fopen fail");
100     while (!feof(fp)) {
101         if (fgets(buf, STATUS_LINE_SIZE, fp) == nullptr) {
102             fclose(fp);
103             return -1;
104         }
105         if (strncmp(buf, "Pid:", PID_STR_SIZE) == 0) {
106             break;
107         }
108     }
109     (void)fclose(fp);
110     return static_cast<pid_t>(ConvertPid(buf));
111 }
112 }  // namespace
113 
GetCurThreadId()114 pid_t inline __attribute__((always_inline)) GetCurThreadId()
115 {
116     if (pthread_getspecific(g_hookTid) == nullptr) {
117         pthread_setspecific(g_hookTid, reinterpret_cast<void *>(GetThreadId()));
118     }
119     return reinterpret_cast<long>((pthread_getspecific(g_hookTid)));
120 }
121 
UpdateThreadName(std::shared_ptr<HookSocketClient> & client)122 bool inline __attribute__((always_inline)) UpdateThreadName(std::shared_ptr<HookSocketClient>& client)
123 {
124     long updateCount = reinterpret_cast<long>(pthread_getspecific(g_updateThreadNameCount));
125     bool ret = true;
126     if (updateCount == 0) {
127         StackRawData tnameData = {{{{0}}}};
128         tnameData.tid = static_cast<uint32_t>(GetCurThreadId());
129         tnameData.type = THREAD_NAME_MSG;
130         prctl(PR_GET_NAME, tnameData.name);
131         ret = client->SendStackWithPayload(&tnameData,
132                                            sizeof(BaseStackRawData) + strlen(tnameData.name) + 1, nullptr, 0);
133         if (!ret) {
134             HILOG_DEBUG(LOG_CORE, "Send thread name failed!");
135             return ret;
136         }
137     }
138     pthread_setspecific(g_updateThreadNameCount,
139                         reinterpret_cast<void *>(updateCount == UPDATE_THEARD_NAME ? 0 : updateCount + 1));
140     return ret;
141 }
142 
GetTagId(std::shared_ptr<HookSocketClient> & client,const char * tagName)143 uint32_t inline __attribute__((always_inline)) GetTagId(std::shared_ptr<HookSocketClient>& client, const char* tagName)
144 {
145     if (tagName == nullptr) {
146         return 0;
147     }
148     uint32_t tagId = 0;
149     bool isNewTag = false;
150     std::unique_lock<std::mutex> lock(g_tagMapMutex);
151     auto it = g_memTagMap.find(tagName);
152     if (it == g_memTagMap.end()) {
153         isNewTag = true;
154         tagId = g_memTagMap.size() + 1;
155         g_memTagMap[tagName] = tagId;
156     } else {
157         tagId = it->second;
158     }
159     lock.unlock();
160     if (isNewTag) {
161         StackRawData tagData = {{{{0}}}};
162         tagData.type = MEMORY_TAG;
163         tagData.tagId = tagId;
164         if (strcpy_s(tagData.name, PATH_MAX + 1, tagName) != 0) {
165             HILOG_ERROR(LOG_CORE, "Set tag name failed");
166         }
167         if (client != nullptr) {
168             client->SendStackWithPayload(&tagData, sizeof(BaseStackRawData) + strlen(tagName) + 1, nullptr, 0);
169         }
170     }
171     return tagId;
172 }
173 
174 static bool IsPidChanged(void);
175 
ohos_malloc_hook_on_start(void)176 bool ohos_malloc_hook_on_start(void)
177 {
178     std::lock_guard<std::recursive_timed_mutex> guard(g_ClientMutex);
179     COMMON::PrintMallinfoLog("before hook(byte) => ");
180     g_hookPid = GetRealPid();
181     g_mallocTimes = 0;
182     if (g_hookClient != nullptr) {
183         HILOG_INFO(LOG_CORE, "hook already started");
184         return true;
185     } else {
186         g_ClientConfig.Reset();
187         g_hookClient = std::make_shared<HookSocketClient>(g_hookPid, &g_ClientConfig);
188     }
189     pthread_key_create(&g_disableHookFlag, nullptr);
190     pthread_setspecific(g_disableHookFlag, nullptr);
191     pthread_key_create(&g_hookTid, nullptr);
192     pthread_setspecific(g_hookTid, nullptr);
193     pthread_key_create(&g_updateThreadNameCount, nullptr);
194     pthread_setspecific(g_updateThreadNameCount, reinterpret_cast<void *>(0));
195     HILOG_INFO(LOG_CORE, "ohos_malloc_hook_on_start");
196     GetMainThreadRuntimeStackRange();
197     constexpr int paramBufferLen = 128;
198     char paramOutBuf[paramBufferLen] = {0};
199     int ret = GetParameter("persist.hiviewdfx.profiler.mem.filter", "", paramOutBuf, paramBufferLen);
200     if (ret > 0) {
201         int min = 0;
202         int max = 0;
203         if (sscanf_s(paramOutBuf, "%d,%d", &min, &max) == 2) { // 2: two parameters.
204             g_maxSize = max > 0 ? max : INT_MAX;
205             g_ClientConfig.filterSize = min > 0 ? min : 0;
206         }
207         HILOG_INFO(LOG_CORE, "persist.hiviewdfx.profiler.mem.filter %s, min %d, max %d",
208                    paramOutBuf, g_ClientConfig.filterSize, g_maxSize);
209     }
210     return true;
211 }
212 
ohos_release_on_end(void *)213 void* ohos_release_on_end(void*)
214 {
215     std::lock_guard<std::recursive_timed_mutex> guard(g_ClientMutex);
216     g_hookClient = nullptr;
217     pthread_key_delete(g_disableHookFlag);
218     pthread_key_delete(g_hookTid);
219     pthread_key_delete(g_updateThreadNameCount);
220     g_ClientConfig.Reset();
221     HILOG_INFO(LOG_CORE, "ohos_malloc_hook_on_end, mallocTimes :%" PRIu64, g_mallocTimes.load());
222     COMMON::PrintMallinfoLog("after hook(byte) => ");
223     return nullptr;
224 }
225 
ohos_malloc_hook_on_end(void)226 bool ohos_malloc_hook_on_end(void)
227 {
228     if (g_hookClient != nullptr) {
229         g_hookClient->Flush();
230     }
231     pthread_t threadEnd;
232     if (pthread_create(&threadEnd, nullptr, ohos_release_on_end, nullptr)) {
233         HILOG_INFO(LOG_CORE, "create ohos_release_on_end fail");
234         return false;
235     }
236     pthread_detach(threadEnd);
237     return true;
238 }
239 
240 #if defined(__aarch64__)
FpUnwind(int maxDepth,uint64_t * ip,int stackSize)241 static int inline __attribute__((always_inline)) FpUnwind(int maxDepth, uint64_t *ip, int stackSize)
242 {
243     void **startfp = (void **)__builtin_frame_address(0);
244     void **fp = startfp;
245     int depth = 0;
246     while (depth < maxDepth) {
247         void **nextFp = (void **)*fp;
248         if (nextFp <= fp) {
249             break;
250         }
251         if (((nextFp - startfp) * sizeof(void *)) > static_cast<unsigned long>(stackSize)) {
252             break;
253         }
254         fp = nextFp;
255         if (*(reinterpret_cast<unsigned long *>(fp + 1)) == 0) {
256             break;
257         }
258         ip[depth++] = *(reinterpret_cast<unsigned long *>(fp + 1));
259     }
260     return depth;
261 }
262 #endif
263 
hook_malloc(void * (* fn)(size_t),size_t size)264 void* hook_malloc(void* (*fn)(size_t), size_t size)
265 {
266     void* ret = nullptr;
267     if (fn) {
268         ret = fn(size);
269     }
270     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
271         return ret;
272     }
273     if (!ohos_set_filter_size(size, ret)) {
274         return ret;
275     }
276 #ifdef PERFORMANCE_DEBUG
277     struct timespec start = {};
278     clock_gettime(CLOCK_REALTIME, &start);
279 #endif
280     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
281     auto holder = weakClient.lock();
282     if (holder == nullptr) {
283         return ret;
284     }
285     if (!UpdateThreadName(holder)) {
286         return ret;
287     }
288     StackRawData rawdata = {{{{0}}}};
289     const char* stackptr = nullptr;
290     const char* stackendptr = nullptr;
291     int stackSize = 0;
292     int fpStackDepth = 0;
293     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
294 
295     if (g_ClientConfig.fpunwind) {
296 #ifdef __aarch64__
297         stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
298         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
299         stackSize = stackendptr - stackptr;
300         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
301         stackSize = 0;
302 #endif
303     } else {
304         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
305         unw_context_t context;
306         unw_getcontext(&context);
307 #if defined(__arm__)
308         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
309                      sizeof(context.regs)) != EOK) {
310             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
311         }
312 #elif defined(__aarch64__)
313         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
314                      sizeof(context.uc_mcontext.regs)) != EOK) {
315             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
316         }
317         regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
318         regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
319 #endif
320         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
321         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
322         stackSize = stackendptr - stackptr;
323     }
324     rawdata.type = MALLOC_MSG;
325     rawdata.pid = static_cast<uint32_t>(g_hookPid);
326     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
327     rawdata.mallocSize = size;
328     rawdata.addr = ret;
329     int realSize = 0;
330     if (g_ClientConfig.fpunwind) {
331         realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
332     } else {
333         realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
334     }
335     holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
336     g_mallocTimes++;
337 #ifdef PERFORMANCE_DEBUG
338     struct timespec end = {};
339     clock_gettime(CLOCK_REALTIME, &end);
340     g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec);
341     g_dataCounts += stackSize;
342     if (g_mallocTimes % PRINT_INTERVAL == 0) {
343         HILOG_ERROR(LOG_CORE,
344             "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64" mean cost = %" PRIu64"\n",
345             g_mallocTimes.load(), g_timeCost.load(), g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load());
346     }
347 #endif
348     return ret;
349 }
350 
hook_valloc(void * (* fn)(size_t),size_t size)351 void* hook_valloc(void* (*fn)(size_t), size_t size)
352 {
353     void* pRet = nullptr;
354     if (fn) {
355         pRet = fn(size);
356     }
357     return pRet;
358 }
359 
hook_calloc(void * (* fn)(size_t,size_t),size_t number,size_t size)360 void* hook_calloc(void* (*fn)(size_t, size_t), size_t number, size_t size)
361 {
362     void* pRet = nullptr;
363     if (fn) {
364         pRet = fn(number, size);
365     }
366     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
367         return pRet;
368     }
369     if (!ohos_set_filter_size(number * size, pRet)) {
370         return pRet;
371     }
372 
373     StackRawData rawdata = {{{{0}}}};
374     const char* stackptr = nullptr;
375     const char* stackendptr = nullptr;
376     int stackSize = 0;
377     int fpStackDepth = 0;
378     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
379 
380     if (g_ClientConfig.fpunwind) {
381 #ifdef __aarch64__
382         stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
383         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
384         stackSize = stackendptr - stackptr;
385         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
386         stackSize = 0;
387 #endif
388     } else {
389         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
390         unw_context_t context;
391         unw_getcontext(&context);
392 #if defined(__arm__)
393         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
394                      sizeof(context.regs)) != EOK) {
395             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
396         }
397 #elif defined(__aarch64__)
398         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
399                      sizeof(context.uc_mcontext.regs)) != EOK) {
400             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
401         }
402         regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
403         regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
404 #endif
405         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
406         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
407         stackSize = stackendptr - stackptr;
408     }
409 
410     rawdata.type = MALLOC_MSG;
411     rawdata.pid = static_cast<uint32_t>(g_hookPid);
412     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
413     rawdata.mallocSize = number * size;
414     rawdata.addr = pRet;
415     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
416     auto holder = weakClient.lock();
417     if (holder != nullptr) {
418         int realSize = 0;
419         if (g_ClientConfig.fpunwind) {
420             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
421         } else {
422             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
423         }
424         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
425     }
426     g_mallocTimes++;
427     return pRet;
428 }
429 
hook_memalign(void * (* fn)(size_t,size_t),size_t align,size_t bytes)430 void* hook_memalign(void* (*fn)(size_t, size_t), size_t align, size_t bytes)
431 {
432     void* pRet = nullptr;
433     if (fn) {
434         pRet = fn(align, bytes);
435     }
436     return pRet;
437 }
438 
hook_realloc(void * (* fn)(void *,size_t),void * ptr,size_t size)439 void* hook_realloc(void* (*fn)(void*, size_t), void* ptr, size_t size)
440 {
441     void* pRet = nullptr;
442     if (fn) {
443         pRet = fn(ptr, size);
444     }
445     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
446         return pRet;
447     }
448     if (!ohos_set_filter_size(size, pRet)) {
449         return pRet;
450     }
451 
452     StackRawData rawdata = {{{{0}}}};
453     StackRawData freeData = {{{{0}}}};
454     const char* stackptr = nullptr;
455     const char* stackendptr = nullptr;
456     int stackSize = 0;
457     int fpStackDepth = 0;
458     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
459 
460     if (g_ClientConfig.fpunwind) {
461 #ifdef __aarch64__
462         stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
463         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
464         stackSize = stackendptr - stackptr;
465         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
466         stackSize = 0;
467         if (g_ClientConfig.freeStackData) {
468             (void)memcpy_s(freeData.ip, sizeof(freeData.ip) / sizeof(uint64_t),
469                            rawdata.ip, sizeof(rawdata.ip) / sizeof(uint64_t));
470         }
471 #endif
472     } else {
473         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
474         unw_context_t context;
475         unw_getcontext(&context);
476 #if defined(__arm__)
477         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
478                      sizeof(context.regs)) != EOK) {
479             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
480         }
481 #elif defined(__aarch64__)
482         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
483                      sizeof(context.uc_mcontext.regs)) != EOK) {
484             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
485         }
486         regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
487         regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
488 #endif
489         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
490         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
491         stackSize = stackendptr - stackptr;
492         if (g_ClientConfig.freeStackData) {
493             (void)memcpy_s(freeData.regs, sizeof(freeData.regs) / sizeof(char),
494                            rawdata.regs, sizeof(rawdata.regs) / sizeof(char));
495         }
496     }
497 
498     rawdata.type = MALLOC_MSG;
499     rawdata.pid = static_cast<uint32_t>(g_hookPid);
500     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
501     rawdata.mallocSize = size;
502     rawdata.addr = pRet;
503     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
504     auto holder = weakClient.lock();
505     if (holder != nullptr) {
506         int realSize = 0;
507         freeData.type = FREE_MSG;
508         freeData.pid = rawdata.pid;
509         freeData.tid = rawdata.tid;
510         freeData.mallocSize = 0;
511         freeData.addr = ptr;
512         freeData.ts = rawdata.ts;
513         if (g_ClientConfig.fpunwind) {
514             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
515         } else {
516             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
517         }
518         holder->SendStackWithPayload(&freeData, sizeof(BaseStackRawData), nullptr, 0); // 0: Don't unwind the freeData
519         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
520     }
521     return pRet;
522 }
523 
hook_malloc_usable_size(size_t (* fn)(void *),void * ptr)524 size_t hook_malloc_usable_size(size_t (*fn)(void*), void* ptr)
525 {
526     size_t ret = 0;
527     if (fn) {
528         ret = fn(ptr);
529     }
530 
531     return ret;
532 }
533 
hook_free(void (* free_func)(void *),void * p)534 void hook_free(void (*free_func)(void*), void* p)
535 {
536     if (free_func) {
537         free_func(p);
538     }
539     if (g_ClientConfig.mallocDisable || IsPidChanged()) {
540         return;
541     }
542     StackRawData rawdata = {{{{0}}}};
543     const char* stackptr = nullptr;
544     const char* stackendptr = nullptr;
545     int stackSize = 0;
546     int fpStackDepth = 0;
547     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
548 
549     if (g_ClientConfig.freeStackData) {
550         if (g_ClientConfig.fpunwind) {
551 #ifdef __aarch64__
552             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
553             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
554             stackSize = stackendptr - stackptr;
555             fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
556             stackSize = 0;
557 #endif
558         } else {
559             unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
560             unw_context_t context;
561             unw_getcontext(&context);
562 #if defined(__arm__)
563             if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
564                          sizeof(context.regs)) != EOK) {
565                 HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
566             }
567 #elif defined(__aarch64__)
568             if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
569                          sizeof(context.uc_mcontext.regs)) != EOK) {
570                 HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
571             }
572             regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
573             regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
574 #endif
575             stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
576             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
577             stackSize = stackendptr - stackptr;
578         }
579     }
580 
581     rawdata.type = FREE_MSG;
582     rawdata.pid = static_cast<uint32_t>(g_hookPid);
583     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
584     rawdata.mallocSize = 0;
585     rawdata.addr = p;
586     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
587     auto holder = weakClient.lock();
588     if (holder != nullptr) {
589         int realSize = 0;
590         if (g_ClientConfig.fpunwind) {
591             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
592         } else {
593             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
594         }
595         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
596     }
597 }
598 
SendMmapFileRawData(int prot,int flags,off_t offset,const std::string & filePath,const StackRawData & rawdata,std::shared_ptr<HookSocketClient> & holder)599 inline void SendMmapFileRawData(int prot, int flags, off_t offset, const std::string& filePath,
600                                 const StackRawData& rawdata, std::shared_ptr<HookSocketClient>& holder)
601 {
602     StackRawData curRawdata = {{{{0}}}};
603     curRawdata.addr = rawdata.addr;
604     curRawdata.pid = static_cast<uint32_t>(g_hookPid);
605     curRawdata.mallocSize = rawdata.mallocSize;
606     curRawdata.mmapArgs.offset = offset;
607     curRawdata.type = OHOS::Developtools::NativeDaemon::MMAP_FILE_TYPE;
608     if (prot & PROT_EXEC) {
609         curRawdata.mmapArgs.flags |= PROT_EXEC;
610     }
611     if (flags & MAP_FIXED) {
612         curRawdata.mmapArgs.flags |= MAP_FIXED;
613         curRawdata.name[0] = '\0';
614         holder->SendStackWithPayload(&curRawdata, sizeof(BaseStackRawData) + 1, nullptr, 0);
615     } else {
616         size_t len = strlen(filePath.c_str()) + 1;
617         (void)strncpy_s(curRawdata.name, PATH_MAX + 1, filePath.c_str(), len);
618         holder->SendStackWithPayload(&curRawdata, sizeof(BaseStackRawData) + len, nullptr, 0);
619     }
620 }
621 
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)622 void* hook_mmap(void*(*fn)(void*, size_t, int, int, int, off_t),
623     void* addr, size_t length, int prot, int flags, int fd, off_t offset)
624 {
625     void* ret = nullptr;
626     if (fn) {
627         ret = fn(addr, length, prot, flags, fd, offset);
628     }
629     if (g_ClientConfig.mmapDisable || IsPidChanged()) {
630         return ret;
631     }
632     StackRawData rawdata = {{{{0}}}};
633     const char* stackptr = nullptr;
634     const char* stackendptr = nullptr;
635     int stackSize = 0;
636     int fpStackDepth = 0;
637     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
638 
639     if (g_ClientConfig.fpunwind) {
640 #ifdef __aarch64__
641         stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
642         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
643         stackSize = stackendptr - stackptr;
644         fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
645         stackSize = 0;
646 #endif
647     } else {
648         unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
649         unw_context_t context;
650         unw_getcontext(&context);
651 #if defined(__arm__)
652         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
653                      sizeof(context.regs)) != EOK) {
654             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
655         }
656 #elif defined(__aarch64__)
657         if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
658                      sizeof(context.uc_mcontext.regs)) != EOK) {
659             HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
660         }
661         regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
662         regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
663 #endif
664         stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
665         GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
666         stackSize = stackendptr - stackptr;
667     }
668 
669     rawdata.type = MMAP_MSG;
670     rawdata.pid = static_cast<uint32_t>(g_hookPid);
671     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
672     rawdata.mallocSize = length;
673     rawdata.addr = ret;
674     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
675     auto holder = weakClient.lock();
676     if (holder == nullptr) {
677         return ret;
678     }
679     if (fd >= 0) {
680         rawdata.type = MMAP_FILE_PAGE_MSG;
681         char path[FD_PATH_LENGTH] = {0};
682         char fileName[PATH_MAX + 1] = {0};
683         (void)snprintf_s(path, FD_PATH_LENGTH, FD_PATH_LENGTH - 1, "/proc/self/fd/%d", fd);
684         ssize_t len = readlink(path, fileName, sizeof(fileName) - 1);
685         if (len != -1) {
686             fileName[len] = '\0';
687             SendMmapFileRawData(prot, flags, offset, fileName, rawdata, holder);
688             char* p = strrchr(fileName, '/');
689             if (p != nullptr) {
690                 rawdata.tagId = GetTagId(holder, &fileName[p - fileName + 1]);
691             } else {
692                 rawdata.tagId = GetTagId(holder, fileName);
693             }
694         } else {
695             HILOG_ERROR(LOG_CORE, "Set mmap fd linked file name failed!");
696         }
697     }
698     if (!UpdateThreadName(holder)) {
699         return ret;
700     }
701     int realSize = 0;
702     if (g_ClientConfig.fpunwind) {
703         realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
704     } else {
705         realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
706     }
707     holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
708     return ret;
709 }
710 
hook_munmap(int (* fn)(void *,size_t),void * addr,size_t length)711 int hook_munmap(int(*fn)(void*, size_t), void* addr, size_t length)
712 {
713     int ret = -1;
714     if (fn) {
715         ret = fn(addr, length);
716     }
717     if (g_ClientConfig.mmapDisable || IsPidChanged()) {
718         return ret;
719     }
720     int stackSize = 0;
721     StackRawData rawdata = {{{{0}}}};
722     const char* stackptr = nullptr;
723     const char* stackendptr = nullptr;
724     int fpStackDepth = 0;
725     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
726 
727     if (g_ClientConfig.munmapStackData) {
728         if (g_ClientConfig.fpunwind) {
729 #ifdef __aarch64__
730             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
731             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
732             stackSize = stackendptr - stackptr;
733             fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
734             stackSize = 0;
735 #endif
736         } else {
737             unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
738             unw_context_t context;
739             unw_getcontext(&context);
740 #if defined(__arm__)
741             if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
742                          sizeof(context.regs)) != EOK) {
743                 HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
744             }
745 #elif defined(__aarch64__)
746             if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
747                          sizeof(context.uc_mcontext.regs)) != EOK) {
748                 HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
749             }
750             regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
751             regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
752 #endif
753             stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
754             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
755             stackSize = stackendptr - stackptr;
756         }
757     }
758 
759     rawdata.type = MUNMAP_MSG;
760     rawdata.pid = static_cast<uint32_t>(g_hookPid);
761     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
762     rawdata.mallocSize = length;
763     rawdata.addr = addr;
764     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
765     auto holder = weakClient.lock();
766     if (holder != nullptr) {
767         int realSize = 0;
768         if (g_ClientConfig.fpunwind) {
769             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
770         } else {
771             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
772         }
773         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
774     }
775     return ret;
776 }
777 
hook_prctl(int (* fn)(int,...),int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5)778 int hook_prctl(int(*fn)(int, ...),
779     int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
780 {
781     int ret = -1;
782     if (fn) {
783         ret = fn(option, arg2, arg3, arg4, arg5);
784     }
785     if (reinterpret_cast<char*>(arg5) == nullptr || IsPidChanged()) {
786         return ret;
787     }
788     if (option == PR_SET_VMA && arg2 == PR_SET_VMA_ANON_NAME) {
789         StackRawData rawdata = {{{{0}}}};
790         clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
791         rawdata.type = PR_SET_VMA_MSG;
792         rawdata.pid = static_cast<uint32_t>(g_hookPid);
793         rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
794         rawdata.mallocSize = arg4;
795         rawdata.addr = reinterpret_cast<void*>(arg3);
796 
797         std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
798         auto holder = weakClient.lock();
799         if (strcpy_s(rawdata.name, PATH_MAX + 1, reinterpret_cast<char*>(arg5))) {
800             HILOG_ERROR(LOG_CORE, "Set tag name failed");
801         }
802         if (holder != nullptr) {
803             holder->SendStackWithPayload(&rawdata,
804                                          sizeof(rawdata) + strlen(reinterpret_cast<char*>(arg5)), nullptr, 0);
805         }
806     }
807     return ret;
808 }
809 
hook_memtrace(void * addr,size_t size,const char * tag,bool isUsing)810 void hook_memtrace(void* addr, size_t size, const char* tag, bool isUsing)
811 {
812     if (!g_ClientConfig.memtraceEnable || IsPidChanged()) {
813         return;
814     }
815     int stackSize = 0;
816     StackRawData rawdata = {{{{0}}}};
817     const char* stackptr = nullptr;
818     const char* stackendptr = nullptr;
819     int fpStackDepth = 0;
820     clock_gettime(g_ClientConfig.clockId, &rawdata.ts);
821 
822     if (isUsing) {
823         if (g_ClientConfig.fpunwind) {
824 #ifdef __aarch64__
825             stackptr = reinterpret_cast<const char*>(__builtin_frame_address(0));
826             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
827             stackSize = stackendptr - stackptr;
828             fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip, stackSize);
829             stackSize = 0;
830 #endif
831         } else {
832             unsigned long* regs = reinterpret_cast<unsigned long*>(&(rawdata.regs));
833             unw_context_t context;
834             unw_getcontext(&context);
835 #if defined(__arm__)
836             if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.regs),
837                          sizeof(context.regs)) != EOK) {
838                 HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
839             }
840 #elif defined(__aarch64__)
841             if (memcpy_s(regs, sizeof(rawdata.regs), reinterpret_cast<char*>(context.uc_mcontext.regs),
842                          sizeof(context.uc_mcontext.regs)) != EOK) {
843                 HILOG_ERROR(LOG_CORE, "memcpy_s regs failed");
844             }
845             regs[RegisterGetSP(buildArchType)] = context.uc_mcontext.sp;
846             regs[RegisterGetIP(buildArchType)] = context.uc_mcontext.pc;
847 #endif
848             stackptr = reinterpret_cast<const char*>(regs[RegisterGetSP(buildArchType)]);
849             GetRuntimeStackEnd(stackptr, &stackendptr, g_hookPid, GetCurThreadId());  // stack end pointer
850             stackSize = stackendptr - stackptr;
851         }
852     }
853     rawdata.type = isUsing ? MEMORY_USING_MSG : MEMORY_UNUSING_MSG;
854     rawdata.pid = static_cast<uint32_t>(g_hookPid);
855     rawdata.tid = static_cast<uint32_t>(GetCurThreadId());
856     rawdata.mallocSize = size;
857     rawdata.addr = addr;
858     std::weak_ptr<HookSocketClient> weakClient = g_hookClient;
859     auto holder = weakClient.lock();
860     rawdata.tagId = isUsing ? GetTagId(holder, tag) : 0;
861     if (holder != nullptr) {
862         int realSize = 0;
863         if (g_ClientConfig.fpunwind) {
864             realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t));
865         } else {
866             realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs);
867         }
868         holder->SendStackWithPayload(&rawdata, realSize, stackptr, stackSize);
869     }
870 }
871 
ohos_malloc_hook_initialize(const MallocDispatchType * malloc_dispatch,bool *,const char *)872 bool ohos_malloc_hook_initialize(const MallocDispatchType*malloc_dispatch, bool*, const char*)
873 {
874     g_dispatch.store(malloc_dispatch);
875     InititalizeIPC();
876     return true;
877 }
ohos_malloc_hook_finalize(void)878 void ohos_malloc_hook_finalize(void)
879 {
880     FinalizeIPC();
881 }
882 
ohos_malloc_hook_malloc(size_t size)883 void* ohos_malloc_hook_malloc(size_t size)
884 {
885     __set_hook_flag(false);
886     void* ret = hook_malloc(GetDispatch()->malloc, size);
887     __set_hook_flag(true);
888     return ret;
889 }
890 
ohos_malloc_hook_realloc(void * ptr,size_t size)891 void* ohos_malloc_hook_realloc(void* ptr, size_t size)
892 {
893     __set_hook_flag(false);
894     void* ret = hook_realloc(GetDispatch()->realloc, ptr, size);
895     __set_hook_flag(true);
896     return ret;
897 }
898 
ohos_malloc_hook_calloc(size_t number,size_t size)899 void* ohos_malloc_hook_calloc(size_t number, size_t size)
900 {
901     __set_hook_flag(false);
902     void* ret = hook_calloc(GetDispatch()->calloc, number, size);
903     __set_hook_flag(true);
904     return ret;
905 }
906 
ohos_malloc_hook_valloc(size_t size)907 void* ohos_malloc_hook_valloc(size_t size)
908 {
909     __set_hook_flag(false);
910     void* ret = hook_valloc(GetDispatch()->valloc, size);
911     __set_hook_flag(true);
912     return ret;
913 }
914 
ohos_malloc_hook_free(void * p)915 void ohos_malloc_hook_free(void* p)
916 {
917     __set_hook_flag(false);
918     hook_free(GetDispatch()->free, p);
919     __set_hook_flag(true);
920 }
921 
ohos_malloc_hook_memalign(size_t alignment,size_t bytes)922 void* ohos_malloc_hook_memalign(size_t alignment, size_t bytes)
923 {
924     __set_hook_flag(false);
925     void* ret = hook_memalign(GetDispatch()->memalign, alignment, bytes);
926     __set_hook_flag(true);
927     return ret;
928 }
929 
ohos_malloc_hook_malloc_usable_size(void * mem)930 size_t ohos_malloc_hook_malloc_usable_size(void* mem)
931 {
932     __set_hook_flag(false);
933     size_t ret = hook_malloc_usable_size(GetDispatch()->malloc_usable_size, mem);
934     __set_hook_flag(true);
935     return ret;
936 }
937 
ohos_malloc_hook_get_hook_flag(void)938 bool ohos_malloc_hook_get_hook_flag(void)
939 {
940     return pthread_getspecific(g_disableHookFlag) == nullptr;
941 }
942 
ohos_malloc_hook_set_hook_flag(bool flag)943 bool ohos_malloc_hook_set_hook_flag(bool flag)
944 {
945     bool oldFlag = ohos_malloc_hook_get_hook_flag();
946     if (flag) {
947         pthread_setspecific(g_disableHookFlag, nullptr);
948     } else {
949         pthread_setspecific(g_disableHookFlag, reinterpret_cast<void *>(1));
950     }
951     return oldFlag;
952 }
953 
ohos_malloc_hook_mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)954 void* ohos_malloc_hook_mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset)
955 {
956     __set_hook_flag(false);
957     void* ret = hook_mmap(GetDispatch()->mmap, addr, length, prot, flags, fd, offset);
958     __set_hook_flag(true);
959     return ret;
960 }
961 
ohos_malloc_hook_munmap(void * addr,size_t length)962 int ohos_malloc_hook_munmap(void* addr, size_t length)
963 {
964     __set_hook_flag(false);
965     int ret = hook_munmap(GetDispatch()->munmap, addr, length);
966     __set_hook_flag(true);
967     return ret;
968 }
969 
ohos_malloc_hook_memtrace(void * addr,size_t size,const char * tag,bool isUsing)970 void ohos_malloc_hook_memtrace(void* addr, size_t size, const char* tag, bool isUsing)
971 {
972     __set_hook_flag(false);
973     hook_memtrace(addr, size, tag, isUsing);
974     __set_hook_flag(true);
975 }
976 
ohos_malloc_hook_prctl(int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5)977 int  ohos_malloc_hook_prctl(int option, unsigned long arg2, unsigned long arg3,
978                             unsigned long arg4, unsigned long arg5)
979 {
980     __set_hook_flag(false);
981     int ret = hook_prctl((GetDispatch()->prctl), option, arg2, arg3, arg4, arg5);
982     __set_hook_flag(true);
983     return ret;
984 }
985 
ohos_set_filter_size(size_t size,void * ret)986 bool ohos_set_filter_size(size_t size, void* ret)
987 {
988     if (g_ClientConfig.filterSize < 0 || size < static_cast<size_t>(g_ClientConfig.filterSize) || size > g_maxSize) {
989         return false;
990     }
991     return true;
992 }
993 
IsPidChanged(void)994 static bool IsPidChanged(void)
995 {
996     if (g_isPidChanged) {
997         return true;
998     }
999     int pid = getpid();
1000     // hap app after pid namespace used
1001     if (pid == PID_NAMESPACE_ID) {
1002         return false;
1003     } else {
1004         // native app & sa service
1005         g_isPidChanged = (g_hookPid != pid);
1006     }
1007     return g_isPidChanged;
1008 }