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 }