1 /**
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "mem_hooks.h"
17
18 #include <iostream>
19 #include <iomanip>
20
21 namespace ark::os::windows::mem_hooks {
22
23 volatile bool enable = false;
24 static bool first = true;
25
GetAllocTypeName(int at)26 static const char *GetAllocTypeName(int at)
27 {
28 switch (at) {
29 case _HOOK_ALLOC:
30 return "_HOOK_ALLOC";
31 case _HOOK_REALLOC:
32 return "_HOOK_REALLOC";
33 case _HOOK_FREE:
34 return "_HOOK_FREE";
35 default:
36 return "unknown AllocType";
37 }
38 }
39
GetBlockTypeName(int bt)40 static const char *GetBlockTypeName(int bt)
41 {
42 switch (bt) {
43 case _CRT_BLOCK:
44 return "_CRT_BLOCK";
45 case _NORMAL_BLOCK:
46 return "_NORMAL_BLOCK";
47 case _FREE_BLOCK:
48 return "_FREE_BLOCK";
49 default:
50 return "unknown BlockType";
51 }
52 }
53
PandaAllocHook(int alloctype,void * data,std::size_t size,int blocktype,long request,const unsigned char * filename,int linenumber)54 int PandaAllocHook(int alloctype, [[maybe_unused]] void *data, std::size_t size, int blocktype,
55 [[maybe_unused]] long request, const unsigned char *filename, int linenumber)
56 {
57 if (!enable) {
58 return true;
59 }
60
61 /* Ignoring internal allocations made by C run-time library functions,
62 * or else it may trap the program in an endless loop.
63 */
64 if (blocktype == _CRT_BLOCK) {
65 return true;
66 }
67
68 constexpr int ALIGN_SIZE = 32;
69
70 if (first) {
71 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << "alloc type";
72 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << "block type";
73 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << "size";
74 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << "filename";
75 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << "linenumber" << std::endl;
76 first = false;
77 }
78
79 const char *alloctypeName = GetAllocTypeName(alloctype);
80 const char *blocktypeName = GetBlockTypeName(blocktype);
81
82 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << alloctypeName;
83 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << blocktypeName;
84 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << static_cast<int>(size);
85 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << filename;
86 std::cout << std::left << std::setfill(' ') << std::setw(ALIGN_SIZE) << linenumber << std::endl;
87
88 return true;
89 }
90
91 /* static */
Initialize()92 void PandaHooks::Initialize()
93 {
94 enable = true;
95 }
96
97 /* static */
Enable()98 void PandaHooks::Enable()
99 {
100 _CrtSetAllocHook(PandaAllocHook);
101 _CrtMemCheckpoint(&begin);
102 _CrtMemDumpAllObjectsSince(&begin);
103 }
104
105 /* static */
Disable()106 void PandaHooks::Disable()
107 {
108 enable = false;
109
110 _CrtMemCheckpoint(&end);
111 _CrtMemDumpAllObjectsSince(&end);
112
113 if (_CrtMemDifference(&out, &begin, &end)) {
114 std::cerr << "Memory leak detected:" << std::endl;
115 _CrtDumpMemoryLeaks();
116 }
117 }
118
119 } // namespace ark::os::windows::mem_hooks
120