106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *         http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci#include <chrono>
1606f6ba60Sopenharmony_ci#include <cstdio>
1706f6ba60Sopenharmony_ci#include <cstdlib>
1806f6ba60Sopenharmony_ci#include <string>
1906f6ba60Sopenharmony_ci#include <vector>
2006f6ba60Sopenharmony_ci#include <dlfcn.h>
2106f6ba60Sopenharmony_ci#include <fcntl.h>
2206f6ba60Sopenharmony_ci#include <memory.h>
2306f6ba60Sopenharmony_ci#include <pthread.h>
2406f6ba60Sopenharmony_ci#include <unistd.h>
2506f6ba60Sopenharmony_ci#include <sys/mman.h>
2606f6ba60Sopenharmony_ci#include <sys/prctl.h>
2706f6ba60Sopenharmony_ci#include <sys/stat.h>
2806f6ba60Sopenharmony_ci#include <sys/syscall.h>
2906f6ba60Sopenharmony_ci#include <sys/types.h>
3006f6ba60Sopenharmony_ci
3106f6ba60Sopenharmony_ci#include "memory_trace.h"
3206f6ba60Sopenharmony_ci#include "securec.h"
3306f6ba60Sopenharmony_ci
3406f6ba60Sopenharmony_ci#pragma clang optimize off
3506f6ba60Sopenharmony_ci
3606f6ba60Sopenharmony_cinamespace {
3706f6ba60Sopenharmony_citypedef char* (*DepthMallocSo)(int depth, int mallocSize);
3806f6ba60Sopenharmony_citypedef void (*DepthFreeSo)(int depth, char *p);
3906f6ba60Sopenharmony_ciconstexpr int MALLOC_SIZE = 1000;
4006f6ba60Sopenharmony_ciconstexpr int ARGC_NUM_MAX = 3;
4106f6ba60Sopenharmony_ciconstexpr int DOUBLE = 2;
4206f6ba60Sopenharmony_ci
4306f6ba60Sopenharmony_ciconstexpr int USLEEP_TIME = 1000;
4406f6ba60Sopenharmony_ci// liba.z.so and libb.z.so for same so.
4506f6ba60Sopenharmony_ci#ifdef __arm__
4606f6ba60Sopenharmony_ciconst std::vector<std::string> VEC_SO_PATH { "/system/lib/liba.z.so", "/system/lib/libb.z.so" };
4706f6ba60Sopenharmony_ci#else
4806f6ba60Sopenharmony_ciconst std::vector<std::string> VEC_SO_PATH { "/system/lib64/liba.z.so", "/system/lib64/libb.z.so" };
4906f6ba60Sopenharmony_ci#endif
5006f6ba60Sopenharmony_ciunsigned int g_stickDepth = 1;
5106f6ba60Sopenharmony_ci}
5206f6ba60Sopenharmony_ci
5306f6ba60Sopenharmony_cistatic void CallocFun()
5406f6ba60Sopenharmony_ci{
5506f6ba60Sopenharmony_ci    static int i = 0;
5606f6ba60Sopenharmony_ci    char* ptr = static_cast<char*>(calloc(1, MALLOC_SIZE / 100));
5706f6ba60Sopenharmony_ci    if (ptr == nullptr) {
5806f6ba60Sopenharmony_ci        fprintf(stderr, "calloc err.\n");
5906f6ba60Sopenharmony_ci        return;
6006f6ba60Sopenharmony_ci    }
6106f6ba60Sopenharmony_ci    fprintf(stderr, "calloc i=%d\n", i);
6206f6ba60Sopenharmony_ci    free(ptr);
6306f6ba60Sopenharmony_ci    i++;
6406f6ba60Sopenharmony_ci}
6506f6ba60Sopenharmony_ci
6606f6ba60Sopenharmony_cistatic void ReallocFun()
6706f6ba60Sopenharmony_ci{
6806f6ba60Sopenharmony_ci    static int i = 0;
6906f6ba60Sopenharmony_ci    char* ptr = static_cast<char*>(calloc(1, MALLOC_SIZE / 10)); // 10: multiple num
7006f6ba60Sopenharmony_ci    if (ptr == nullptr) {
7106f6ba60Sopenharmony_ci        fprintf(stderr, "calloc err.\n");
7206f6ba60Sopenharmony_ci        return;
7306f6ba60Sopenharmony_ci    }
7406f6ba60Sopenharmony_ci    ptr = static_cast<char*>(realloc(ptr, MALLOC_SIZE * 10)); // 10: multiple num
7506f6ba60Sopenharmony_ci    if (ptr == nullptr) {
7606f6ba60Sopenharmony_ci        fprintf(stderr, "realloc err.\n");
7706f6ba60Sopenharmony_ci        return;
7806f6ba60Sopenharmony_ci    }
7906f6ba60Sopenharmony_ci    fprintf(stderr, "realloc i=%d\n", i);
8006f6ba60Sopenharmony_ci    free(ptr);
8106f6ba60Sopenharmony_ci    i++;
8206f6ba60Sopenharmony_ci}
8306f6ba60Sopenharmony_ci
8406f6ba60Sopenharmony_cistatic bool DepthMallocFree(int depth = 0, int mallocSize = 100)
8506f6ba60Sopenharmony_ci{
8606f6ba60Sopenharmony_ci    if (depth < 0 || mallocSize <= 0) {
8706f6ba60Sopenharmony_ci        return false;
8806f6ba60Sopenharmony_ci    }
8906f6ba60Sopenharmony_ci    if (depth == 0) {
9006f6ba60Sopenharmony_ci        char* ptr = static_cast<char*>(malloc(mallocSize));
9106f6ba60Sopenharmony_ci        if (ptr == nullptr) {
9206f6ba60Sopenharmony_ci            fprintf(stderr, "malloc err.\n");
9306f6ba60Sopenharmony_ci            return false;
9406f6ba60Sopenharmony_ci        }
9506f6ba60Sopenharmony_ci        fprintf(stderr, "%s\n", __func__);
9606f6ba60Sopenharmony_ci        *ptr = 'a';
9706f6ba60Sopenharmony_ci        free(ptr);
9806f6ba60Sopenharmony_ci        return true;
9906f6ba60Sopenharmony_ci    }
10006f6ba60Sopenharmony_ci    return (DepthMallocFree(depth - 1, mallocSize));
10106f6ba60Sopenharmony_ci}
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_cistatic void DlopenAndCloseSo(const std::string& filePath, int size)
10406f6ba60Sopenharmony_ci{
10506f6ba60Sopenharmony_ci    void* handle = nullptr;
10606f6ba60Sopenharmony_ci    DepthMallocSo mallocFunc = nullptr;
10706f6ba60Sopenharmony_ci    DepthFreeSo freeFunc = nullptr;
10806f6ba60Sopenharmony_ci
10906f6ba60Sopenharmony_ci    fprintf(stderr, "dlopen %s %d!!!\n", filePath.data(), size);
11006f6ba60Sopenharmony_ci    usleep(USLEEP_TIME * 300); // 300 ms
11106f6ba60Sopenharmony_ci    handle = dlopen(filePath.data(), RTLD_LAZY);
11206f6ba60Sopenharmony_ci    if (handle == nullptr) {
11306f6ba60Sopenharmony_ci        fprintf(stderr, "library not exist!\n");
11406f6ba60Sopenharmony_ci        exit(0);
11506f6ba60Sopenharmony_ci    }
11606f6ba60Sopenharmony_ci    mallocFunc = (DepthMallocSo)dlsym(handle, "DepthMallocSo");
11706f6ba60Sopenharmony_ci    freeFunc = (DepthFreeSo)dlsym(handle, "DepthFreeSo");
11806f6ba60Sopenharmony_ci    if (mallocFunc == nullptr || freeFunc == nullptr) {
11906f6ba60Sopenharmony_ci        fprintf(stderr, "function not exist!\n");
12006f6ba60Sopenharmony_ci        exit(0);
12106f6ba60Sopenharmony_ci    }
12206f6ba60Sopenharmony_ci    char* ptr = nullptr;
12306f6ba60Sopenharmony_ci    for (size_t i = 0; i < 20; i++) { // 20: loop count
12406f6ba60Sopenharmony_ci        ptr = mallocFunc(g_stickDepth, size);
12506f6ba60Sopenharmony_ci        *ptr = 'a';
12606f6ba60Sopenharmony_ci        freeFunc(g_stickDepth, ptr);
12706f6ba60Sopenharmony_ci    }
12806f6ba60Sopenharmony_ci    if (handle != nullptr) {
12906f6ba60Sopenharmony_ci        usleep(USLEEP_TIME * 300); // 300 ms
13006f6ba60Sopenharmony_ci        dlclose(handle);
13106f6ba60Sopenharmony_ci    }
13206f6ba60Sopenharmony_ci}
13306f6ba60Sopenharmony_ci
13406f6ba60Sopenharmony_cistatic int MmapAndMunMap()
13506f6ba60Sopenharmony_ci{
13606f6ba60Sopenharmony_ci    size_t size = (1024);
13706f6ba60Sopenharmony_ci
13806f6ba60Sopenharmony_ci    char* ptr = static_cast<char*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
13906f6ba60Sopenharmony_ci    if (ptr == MAP_FAILED) {
14006f6ba60Sopenharmony_ci        fprintf(stderr, "Mmap err.\n");
14106f6ba60Sopenharmony_ci        ptr = nullptr;
14206f6ba60Sopenharmony_ci        return 1;
14306f6ba60Sopenharmony_ci    }
14406f6ba60Sopenharmony_ci
14506f6ba60Sopenharmony_ci    (void)memset_s(ptr, size, 0, size);
14606f6ba60Sopenharmony_ci    munmap(ptr, size);
14706f6ba60Sopenharmony_ci    return 0;
14806f6ba60Sopenharmony_ci}
14906f6ba60Sopenharmony_ci
15006f6ba60Sopenharmony_cistatic void Fun1()
15106f6ba60Sopenharmony_ci{
15206f6ba60Sopenharmony_ci    static int i = 0;
15306f6ba60Sopenharmony_ci    char* ptr = static_cast<char*>(malloc(MALLOC_SIZE));
15406f6ba60Sopenharmony_ci    if (ptr == nullptr) {
15506f6ba60Sopenharmony_ci        fprintf(stderr, "malloc err.\n");
15606f6ba60Sopenharmony_ci        return;
15706f6ba60Sopenharmony_ci    }
15806f6ba60Sopenharmony_ci    fprintf(stderr, "i=%d\n", i);
15906f6ba60Sopenharmony_ci    *ptr = 'a';
16006f6ba60Sopenharmony_ci    free(ptr);
16106f6ba60Sopenharmony_ci    i++;
16206f6ba60Sopenharmony_ci    MmapAndMunMap();
16306f6ba60Sopenharmony_ci    CallocFun();
16406f6ba60Sopenharmony_ci    ReallocFun();
16506f6ba60Sopenharmony_ci}
16606f6ba60Sopenharmony_ci
16706f6ba60Sopenharmony_cistatic void Fun2()
16806f6ba60Sopenharmony_ci{
16906f6ba60Sopenharmony_ci    Fun1();
17006f6ba60Sopenharmony_ci    static int i = 0;
17106f6ba60Sopenharmony_ci    char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
17206f6ba60Sopenharmony_ci    if (ptr == nullptr) {
17306f6ba60Sopenharmony_ci        fprintf(stderr, "malloc err.\n");
17406f6ba60Sopenharmony_ci        return;
17506f6ba60Sopenharmony_ci    }
17606f6ba60Sopenharmony_ci    fprintf(stderr, "i=%d\n", i);
17706f6ba60Sopenharmony_ci    *ptr = 'a';
17806f6ba60Sopenharmony_ci    if (i % DOUBLE == 0) {
17906f6ba60Sopenharmony_ci        free(ptr);
18006f6ba60Sopenharmony_ci    }
18106f6ba60Sopenharmony_ci    i++;
18206f6ba60Sopenharmony_ci}
18306f6ba60Sopenharmony_ci
18406f6ba60Sopenharmony_cistatic void Fun3()
18506f6ba60Sopenharmony_ci{
18606f6ba60Sopenharmony_ci    Fun2();
18706f6ba60Sopenharmony_ci    static int i = 0;
18806f6ba60Sopenharmony_ci    char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
18906f6ba60Sopenharmony_ci    if (ptr == nullptr) {
19006f6ba60Sopenharmony_ci        fprintf(stderr, "malloc err.\n");
19106f6ba60Sopenharmony_ci        return;
19206f6ba60Sopenharmony_ci    }
19306f6ba60Sopenharmony_ci    fprintf(stderr, "i=%d\n", i);
19406f6ba60Sopenharmony_ci    *ptr = 'a';
19506f6ba60Sopenharmony_ci    if (i % DOUBLE == 0) {
19606f6ba60Sopenharmony_ci        free(ptr);
19706f6ba60Sopenharmony_ci    }
19806f6ba60Sopenharmony_ci    i++;
19906f6ba60Sopenharmony_ci    DlopenAndCloseSo(VEC_SO_PATH[0], MALLOC_SIZE * DOUBLE);
20006f6ba60Sopenharmony_ci}
20106f6ba60Sopenharmony_ci
20206f6ba60Sopenharmony_cistatic void Fun4()
20306f6ba60Sopenharmony_ci{
20406f6ba60Sopenharmony_ci    Fun3();
20506f6ba60Sopenharmony_ci    static int i = 0;
20606f6ba60Sopenharmony_ci    char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
20706f6ba60Sopenharmony_ci    if (ptr == nullptr) {
20806f6ba60Sopenharmony_ci        fprintf(stderr, "malloc err.\n");
20906f6ba60Sopenharmony_ci        return;
21006f6ba60Sopenharmony_ci    }
21106f6ba60Sopenharmony_ci    fprintf(stderr, "i=%d\n", i);
21206f6ba60Sopenharmony_ci    *ptr = 'a';
21306f6ba60Sopenharmony_ci    if (i % DOUBLE == 0) {
21406f6ba60Sopenharmony_ci        free(ptr);
21506f6ba60Sopenharmony_ci    }
21606f6ba60Sopenharmony_ci    i++;
21706f6ba60Sopenharmony_ci}
21806f6ba60Sopenharmony_ci
21906f6ba60Sopenharmony_cistatic void Fun5()
22006f6ba60Sopenharmony_ci{
22106f6ba60Sopenharmony_ci    Fun4();
22206f6ba60Sopenharmony_ci    static int i = 0;
22306f6ba60Sopenharmony_ci    char *ptr = static_cast<char*>(malloc(MALLOC_SIZE));
22406f6ba60Sopenharmony_ci    if (ptr == nullptr) {
22506f6ba60Sopenharmony_ci        fprintf(stderr, "malloc err.\n");
22606f6ba60Sopenharmony_ci        return;
22706f6ba60Sopenharmony_ci    }
22806f6ba60Sopenharmony_ci    fprintf(stderr, "i=%d\n", i);
22906f6ba60Sopenharmony_ci    *ptr = 'a';
23006f6ba60Sopenharmony_ci    if (i % DOUBLE == 0) {
23106f6ba60Sopenharmony_ci        free(ptr);
23206f6ba60Sopenharmony_ci    }
23306f6ba60Sopenharmony_ci    i++;
23406f6ba60Sopenharmony_ci    DepthMallocFree(g_stickDepth * 30); // 30: depth count
23506f6ba60Sopenharmony_ci    DlopenAndCloseSo(VEC_SO_PATH[1], MALLOC_SIZE * 3); // 3: multiple num
23606f6ba60Sopenharmony_ci}
23706f6ba60Sopenharmony_ci
23806f6ba60Sopenharmony_cistatic void* HhreadFuncCpp(void* param)
23906f6ba60Sopenharmony_ci{
24006f6ba60Sopenharmony_ci    std::string name = "thread";
24106f6ba60Sopenharmony_ci    name = name + std::to_string(gettid());
24206f6ba60Sopenharmony_ci    prctl(PR_SET_NAME, name.c_str());
24306f6ba60Sopenharmony_ci    int forNum = *static_cast<int*>(param);
24406f6ba60Sopenharmony_ci    for (int num = 0; num < forNum; num++) {
24506f6ba60Sopenharmony_ci        fprintf(stderr, "thread %d:num=%d\n", gettid(), num);
24606f6ba60Sopenharmony_ci        Fun5();
24706f6ba60Sopenharmony_ci    }
24806f6ba60Sopenharmony_ci    return nullptr;
24906f6ba60Sopenharmony_ci}
25006f6ba60Sopenharmony_ci
25106f6ba60Sopenharmony_cistatic void TestMemoryMap()
25206f6ba60Sopenharmony_ci{
25306f6ba60Sopenharmony_ci    constexpr int smallSize = 4096;
25406f6ba60Sopenharmony_ci    constexpr int bigSize = 8192;
25506f6ba60Sopenharmony_ci    int fd = open("/bin/hiebpf", O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IROTH);
25606f6ba60Sopenharmony_ci    if (fd < 0) {
25706f6ba60Sopenharmony_ci        printf("open %s failed\n", "/bin/hiebpf");
25806f6ba60Sopenharmony_ci        return;
25906f6ba60Sopenharmony_ci    }
26006f6ba60Sopenharmony_ci
26106f6ba60Sopenharmony_ci    void* mapAddr1 = mmap(nullptr, smallSize, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0);
26206f6ba60Sopenharmony_ci    if (mapAddr1 == MAP_FAILED) {
26306f6ba60Sopenharmony_ci        printf("named mmap failed\n");
26406f6ba60Sopenharmony_ci        close(fd);
26506f6ba60Sopenharmony_ci        return;
26606f6ba60Sopenharmony_ci    }
26706f6ba60Sopenharmony_ci    printf("named mmap size: 4096, fd: %d\n", fd);
26806f6ba60Sopenharmony_ci
26906f6ba60Sopenharmony_ci    void* mapAddr2 = mmap(nullptr, bigSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
27006f6ba60Sopenharmony_ci    if (mapAddr2 == MAP_FAILED) {
27106f6ba60Sopenharmony_ci        printf("anonymous mmap failed\n");
27206f6ba60Sopenharmony_ci        close(fd);
27306f6ba60Sopenharmony_ci        munmap(mapAddr1, smallSize);
27406f6ba60Sopenharmony_ci        return;
27506f6ba60Sopenharmony_ci    }
27606f6ba60Sopenharmony_ci    printf("anonymous mmap size: 8192\n");
27706f6ba60Sopenharmony_ci
27806f6ba60Sopenharmony_ci    memtrace(reinterpret_cast<void*>(0x123456), 3333, "memtrace_test", true); // 3333 num
27906f6ba60Sopenharmony_ci    printf("memtrace(0x123456, 3333, \"memtrace_test\", true)\n");
28006f6ba60Sopenharmony_ci
28106f6ba60Sopenharmony_ci    memtrace(reinterpret_cast<void*>(0x123456), 3333, "memtrace_test", false); // 3333 num
28206f6ba60Sopenharmony_ci    printf("memtrace(0x123456, 3333, \"memtrace_test\", false)\n");
28306f6ba60Sopenharmony_ci    close(fd);
28406f6ba60Sopenharmony_ci    munmap(mapAddr1, smallSize);
28506f6ba60Sopenharmony_ci    munmap(mapAddr2, bigSize);
28606f6ba60Sopenharmony_ci}
28706f6ba60Sopenharmony_ci
28806f6ba60Sopenharmony_ciint main(int argc, char *argv[])
28906f6ba60Sopenharmony_ci{
29006f6ba60Sopenharmony_ci    int threadNum = 1;
29106f6ba60Sopenharmony_ci    int forNum = 10;
29206f6ba60Sopenharmony_ci    if  (argc == ARGC_NUM_MAX) {
29306f6ba60Sopenharmony_ci        if (atoi(argv[1]) > 0 && atoi(argv[1]) <= 10) { // 10: max threads
29406f6ba60Sopenharmony_ci            threadNum = atoi(argv[1]);
29506f6ba60Sopenharmony_ci        }
29606f6ba60Sopenharmony_ci        if (atoi(argv[2]) > 0 && atoi(argv[2]) <= 100) { // 2: args num. 100: max value
29706f6ba60Sopenharmony_ci            forNum = atoi(argv[2]); // 2: args num
29806f6ba60Sopenharmony_ci        }
29906f6ba60Sopenharmony_ci    } else if (argc > ARGC_NUM_MAX) {
30006f6ba60Sopenharmony_ci        printf("command error, argc must <= %d\n", ARGC_NUM_MAX);
30106f6ba60Sopenharmony_ci        return 0;
30206f6ba60Sopenharmony_ci    }
30306f6ba60Sopenharmony_ci    fprintf(stderr, "start.Enter or send signal for next.\n");
30406f6ba60Sopenharmony_ci    getchar();
30506f6ba60Sopenharmony_ci    TestMemoryMap();
30606f6ba60Sopenharmony_ci
30706f6ba60Sopenharmony_ci    fprintf(stderr, "forNum = %d, threadNum = %d\n", forNum, threadNum);
30806f6ba60Sopenharmony_ci    fprintf(stderr, "Notice: need copy libnativetest_so.z.so for %s, %s\n",
30906f6ba60Sopenharmony_ci            VEC_SO_PATH[0].data(), VEC_SO_PATH[1].data());
31006f6ba60Sopenharmony_ci    pthread_t* thrArray = new (std::nothrow) pthread_t[threadNum];
31106f6ba60Sopenharmony_ci    if (!thrArray) {
31206f6ba60Sopenharmony_ci        printf("new thread array failed.\n");
31306f6ba60Sopenharmony_ci        return 1;
31406f6ba60Sopenharmony_ci    }
31506f6ba60Sopenharmony_ci    int idx;
31606f6ba60Sopenharmony_ci    for (idx = 0; idx < threadNum; ++idx) {
31706f6ba60Sopenharmony_ci        if (pthread_create(thrArray + idx, nullptr, HhreadFuncCpp, static_cast<void*>(&forNum)) != 0) {
31806f6ba60Sopenharmony_ci            printf("Creating thread failed.\n");
31906f6ba60Sopenharmony_ci        }
32006f6ba60Sopenharmony_ci    }
32106f6ba60Sopenharmony_ci    for (idx = 0; idx < threadNum; ++idx) {
32206f6ba60Sopenharmony_ci        pthread_join(thrArray[idx], nullptr);
32306f6ba60Sopenharmony_ci    }
32406f6ba60Sopenharmony_ci    delete []thrArray;
32506f6ba60Sopenharmony_ci
32606f6ba60Sopenharmony_ci    fprintf(stderr, "end.\n");
32706f6ba60Sopenharmony_ci    return 0;
32806f6ba60Sopenharmony_ci}
32906f6ba60Sopenharmony_ci
33006f6ba60Sopenharmony_ci#pragma clang optimize on