1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. 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#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 36namespace { 37typedef char* (*DepthMallocSo)(int depth, int mallocSize); 38typedef void (*DepthFreeSo)(int depth, char *p); 39constexpr int MALLOC_SIZE = 1000; 40constexpr int ARGC_NUM_MAX = 3; 41constexpr int DOUBLE = 2; 42 43constexpr int USLEEP_TIME = 1000; 44// liba.z.so and libb.z.so for same so. 45#ifdef __arm__ 46const std::vector<std::string> VEC_SO_PATH { "/system/lib/liba.z.so", "/system/lib/libb.z.so" }; 47#else 48const std::vector<std::string> VEC_SO_PATH { "/system/lib64/liba.z.so", "/system/lib64/libb.z.so" }; 49#endif 50unsigned int g_stickDepth = 1; 51} 52 53static 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 66static 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 84static 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 103static 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 134static 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 150static 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 167static 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 184static 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 202static 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 219static 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 238static 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 251static 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_IRGRP | S_IROTH); 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 288int 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