• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include <chrono>
16 #include <cstdio>
17 #include <cstdlib>
18 #include <string>
19 #include <vector>
20 #include <dlfcn.h>
21 #include <fcntl.h>
22 #include <memory.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <sys/prctl.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30 
31 #include "memory_trace.h"
32 #include "securec.h"
33 
34 #pragma clang optimize off
35 
36 namespace {
37 typedef char* (*DepthMallocSo)(int depth, int mallocSize);
38 typedef void (*DepthFreeSo)(int depth, char *p);
39 constexpr int MALLOC_SIZE = 1000;
40 constexpr int ARGC_NUM_MAX = 3;
41 constexpr int DOUBLE = 2;
42 
43 constexpr int USLEEP_TIME = 1000;
44 // liba.z.so and libb.z.so for same so.
45 #ifdef __arm__
46 const std::vector<std::string> VEC_SO_PATH { "/system/lib/liba.z.so", "/system/lib/libb.z.so" };
47 #else
48 const std::vector<std::string> VEC_SO_PATH { "/system/lib64/liba.z.so", "/system/lib64/libb.z.so" };
49 #endif
50 unsigned int g_stickDepth = 1;
51 }
52 
CallocFun()53 static void CallocFun()
54 {
55     static int i = 0;
56     char* ptr = static_cast<char*>(calloc(1, MALLOC_SIZE / 100));
57     if (ptr == nullptr) {
58         fprintf(stderr, "calloc err.\n");
59         return;
60     }
61     fprintf(stderr, "calloc i=%d\n", i);
62     free(ptr);
63     i++;
64 }
65 
ReallocFun()66 static void ReallocFun()
67 {
68     static int i = 0;
69     char* ptr = static_cast<char*>(calloc(1, MALLOC_SIZE / 10)); // 10: multiple num
70     if (ptr == nullptr) {
71         fprintf(stderr, "calloc err.\n");
72         return;
73     }
74     ptr = static_cast<char*>(realloc(ptr, MALLOC_SIZE * 10)); // 10: multiple num
75     if (ptr == nullptr) {
76         fprintf(stderr, "realloc err.\n");
77         return;
78     }
79     fprintf(stderr, "realloc i=%d\n", i);
80     free(ptr);
81     i++;
82 }
83 
DepthMallocFree(int depth=0,int mallocSize=100)84 static bool DepthMallocFree(int depth = 0, int mallocSize = 100)
85 {
86     if (depth < 0 || mallocSize <= 0) {
87         return false;
88     }
89     if (depth == 0) {
90         char* ptr = static_cast<char*>(malloc(mallocSize));
91         if (ptr == nullptr) {
92             fprintf(stderr, "malloc err.\n");
93             return false;
94         }
95         fprintf(stderr, "%s\n", __func__);
96         *ptr = 'a';
97         free(ptr);
98         return true;
99     }
100     return (DepthMallocFree(depth - 1, mallocSize));
101 }
102 
DlopenAndCloseSo(const std::string & filePath,int size)103 static void DlopenAndCloseSo(const std::string& filePath, int size)
104 {
105     void* handle = nullptr;
106     DepthMallocSo mallocFunc = nullptr;
107     DepthFreeSo freeFunc = nullptr;
108 
109     fprintf(stderr, "dlopen %s %d!!!\n", filePath.data(), size);
110     usleep(USLEEP_TIME * 300); // 300 ms
111     handle = dlopen(filePath.data(), RTLD_LAZY);
112     if (handle == nullptr) {
113         fprintf(stderr, "library not exist!\n");
114         exit(0);
115     }
116     mallocFunc = (DepthMallocSo)dlsym(handle, "DepthMallocSo");
117     freeFunc = (DepthFreeSo)dlsym(handle, "DepthFreeSo");
118     if (mallocFunc == nullptr || freeFunc == nullptr) {
119         fprintf(stderr, "function not exist!\n");
120         exit(0);
121     }
122     char* ptr = nullptr;
123     for (size_t i = 0; i < 20; i++) { // 20: loop count
124         ptr = mallocFunc(g_stickDepth, size);
125         *ptr = 'a';
126         freeFunc(g_stickDepth, ptr);
127     }
128     if (handle != nullptr) {
129         usleep(USLEEP_TIME * 300); // 300 ms
130         dlclose(handle);
131     }
132 }
133 
MmapAndMunMap()134 static int MmapAndMunMap()
135 {
136     size_t size = (1024);
137 
138     char* ptr = static_cast<char*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
139     if (ptr == MAP_FAILED) {
140         fprintf(stderr, "Mmap err.\n");
141         ptr = nullptr;
142         return 1;
143     }
144 
145     (void)memset_s(ptr, size, 0, size);
146     munmap(ptr, size);
147     return 0;
148 }
149 
Fun1()150 static void Fun1()
151 {
152     static int i = 0;
153     char* ptr = static_cast<char*>(malloc(MALLOC_SIZE));
154     if (ptr == nullptr) {
155         fprintf(stderr, "malloc err.\n");
156         return;
157     }
158     fprintf(stderr, "i=%d\n", i);
159     *ptr = 'a';
160     free(ptr);
161     i++;
162     MmapAndMunMap();
163     CallocFun();
164     ReallocFun();
165 }
166 
Fun2()167 static void Fun2()
168 {
169     Fun1();
170     static int i = 0;
171     char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
172     if (ptr == nullptr) {
173         fprintf(stderr, "malloc err.\n");
174         return;
175     }
176     fprintf(stderr, "i=%d\n", i);
177     *ptr = 'a';
178     if (i % DOUBLE == 0) {
179         free(ptr);
180     }
181     i++;
182 }
183 
Fun3()184 static void Fun3()
185 {
186     Fun2();
187     static int i = 0;
188     char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
189     if (ptr == nullptr) {
190         fprintf(stderr, "malloc err.\n");
191         return;
192     }
193     fprintf(stderr, "i=%d\n", i);
194     *ptr = 'a';
195     if (i % DOUBLE == 0) {
196         free(ptr);
197     }
198     i++;
199     DlopenAndCloseSo(VEC_SO_PATH[0], MALLOC_SIZE * DOUBLE);
200 }
201 
Fun4()202 static void Fun4()
203 {
204     Fun3();
205     static int i = 0;
206     char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
207     if (ptr == nullptr) {
208         fprintf(stderr, "malloc err.\n");
209         return;
210     }
211     fprintf(stderr, "i=%d\n", i);
212     *ptr = 'a';
213     if (i % DOUBLE == 0) {
214         free(ptr);
215     }
216     i++;
217 }
218 
Fun5()219 static void Fun5()
220 {
221     Fun4();
222     static int i = 0;
223     char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
224     if (ptr == nullptr) {
225         fprintf(stderr, "malloc err.\n");
226         return;
227     }
228     fprintf(stderr, "i=%d\n", i);
229     *ptr = 'a';
230     if (i % DOUBLE == 0) {
231         free(ptr);
232     }
233     i++;
234     DepthMallocFree(g_stickDepth * 30); // 30: depth count
235     DlopenAndCloseSo(VEC_SO_PATH[1], MALLOC_SIZE * 3); // 3: multiple num
236 }
237 
HhreadFuncCpp(void * param)238 static void* HhreadFuncCpp(void* param)
239 {
240     std::string name = "thread";
241     name = name + std::to_string(gettid());
242     prctl(PR_SET_NAME, name.c_str());
243     int forNum = *static_cast<int*>(param);
244     for (int num = 0; num < forNum; num++) {
245         fprintf(stderr, "thread %d:num=%d\n", gettid(), num);
246         Fun5();
247     }
248     return nullptr;
249 }
250 
TestMemoryMap()251 static void TestMemoryMap()
252 {
253     constexpr int smallSize = 4096;
254     constexpr int bigSize = 8192;
255     int fd = open("/bin/hiebpf", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
256     if (fd < 0) {
257         printf("open %s failed\n", "/bin/hiebpf");
258         return;
259     }
260 
261     void* mapAddr1 = mmap(nullptr, smallSize, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0);
262     if (mapAddr1 == MAP_FAILED) {
263         printf("named mmap failed\n");
264         close(fd);
265         return;
266     }
267     printf("named mmap size: 4096, fd: %d\n", fd);
268 
269     void* mapAddr2 = mmap(nullptr, bigSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
270     if (mapAddr2 == MAP_FAILED) {
271         printf("anonymous mmap failed\n");
272         close(fd);
273         munmap(mapAddr1, smallSize);
274         return;
275     }
276     printf("anonymous mmap size: 8192\n");
277 
278     memtrace(reinterpret_cast<void*>(0x123456), 3333, "memtrace_test", true); // 3333 num
279     printf("memtrace(0x123456, 3333, \"memtrace_test\", true)\n");
280 
281     memtrace(reinterpret_cast<void*>(0x123456), 3333, "memtrace_test", false); // 3333 num
282     printf("memtrace(0x123456, 3333, \"memtrace_test\", false)\n");
283     close(fd);
284     munmap(mapAddr1, smallSize);
285     munmap(mapAddr2, bigSize);
286 }
287 
main(int argc,char * argv[])288 int main(int argc, char *argv[])
289 {
290     int threadNum = 1;
291     int forNum = 10;
292     if  (argc == ARGC_NUM_MAX) {
293         if (atoi(argv[1]) > 0 && atoi(argv[1]) <= 10) { // 10: max threads
294             threadNum = atoi(argv[1]);
295         }
296         if (atoi(argv[2]) > 0 && atoi(argv[2]) <= 100) { // 2: args num. 100: max value
297             forNum = atoi(argv[2]); // 2: args num
298         }
299     } else if (argc > ARGC_NUM_MAX) {
300         printf("command error, argc must <= %d\n", ARGC_NUM_MAX);
301         return 0;
302     }
303     fprintf(stderr, "start.Enter or send signal for next.\n");
304     getchar();
305     TestMemoryMap();
306 
307     fprintf(stderr, "forNum = %d, threadNum = %d\n", forNum, threadNum);
308     fprintf(stderr, "Notice: need copy libnativetest_so.z.so for %s, %s\n",
309             VEC_SO_PATH[0].data(), VEC_SO_PATH[1].data());
310     pthread_t* thrArray = new (std::nothrow) pthread_t[threadNum];
311     if (!thrArray) {
312         printf("new thread array failed.\n");
313         return 1;
314     }
315     int idx;
316     for (idx = 0; idx < threadNum; ++idx) {
317         if (pthread_create(thrArray + idx, nullptr, HhreadFuncCpp, static_cast<void*>(&forNum)) != 0) {
318             printf("Creating thread failed.\n");
319         }
320     }
321     for (idx = 0; idx < threadNum; ++idx) {
322         pthread_join(thrArray[idx], nullptr);
323     }
324     delete []thrArray;
325 
326     fprintf(stderr, "end.\n");
327     return 0;
328 }
329 
330 #pragma clang optimize on