155c6b4c7Sopenharmony_ci/*
255c6b4c7Sopenharmony_ci * Copyright (c) 2020 Huawei Device Co., Ltd.
355c6b4c7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
455c6b4c7Sopenharmony_ci * you may not use this file except in compliance with the License.
555c6b4c7Sopenharmony_ci * You may obtain a copy of the License at
655c6b4c7Sopenharmony_ci *
755c6b4c7Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
855c6b4c7Sopenharmony_ci *
955c6b4c7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1055c6b4c7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1155c6b4c7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1255c6b4c7Sopenharmony_ci * See the License for the specific language governing permissions and
1355c6b4c7Sopenharmony_ci * limitations under the License.
1455c6b4c7Sopenharmony_ci */
1555c6b4c7Sopenharmony_ci
1655c6b4c7Sopenharmony_ci#include <errno.h>
1755c6b4c7Sopenharmony_ci#include <fcntl.h>
1855c6b4c7Sopenharmony_ci#include <stdio.h>
1955c6b4c7Sopenharmony_ci#include <string.h>
2055c6b4c7Sopenharmony_ci#include <unistd.h>
2155c6b4c7Sopenharmony_ci
2255c6b4c7Sopenharmony_ci#include <sys/ioctl.h>
2355c6b4c7Sopenharmony_ci#include <sys/stat.h>
2455c6b4c7Sopenharmony_ci#include <sys/types.h>
2555c6b4c7Sopenharmony_ci
2655c6b4c7Sopenharmony_ci#include "securec.h"
2755c6b4c7Sopenharmony_ci
2855c6b4c7Sopenharmony_ci#define HIDUMPER_DEVICE  "/dev/hidumper"
2955c6b4c7Sopenharmony_ci#define USER_FAULT_ADDR  0x3
3055c6b4c7Sopenharmony_ci#define USER_FAULT_VALUE 0x4
3155c6b4c7Sopenharmony_ci#define PATH_MAX_LEN     256
3255c6b4c7Sopenharmony_ci
3355c6b4c7Sopenharmony_ci#define ONE_OF_ARGC_PARAMETERS           1
3455c6b4c7Sopenharmony_ci#define TWO_OF_ARGC_PARAMETERS           2
3555c6b4c7Sopenharmony_ci#define THREE_OF_ARGC_PARAMETERS         3
3655c6b4c7Sopenharmony_ci#define FOUR_OF_ARGC_PARAMETERS          4
3755c6b4c7Sopenharmony_ci#define FIVE_OF_ARGC_PARAMETERS          5
3855c6b4c7Sopenharmony_ci
3955c6b4c7Sopenharmony_ci#define BUF_SIZE_16                      16
4055c6b4c7Sopenharmony_ci
4155c6b4c7Sopenharmony_cienum MemDumpType {
4255c6b4c7Sopenharmony_ci    DUMP_TO_STDOUT,
4355c6b4c7Sopenharmony_ci    DUMP_REGION_TO_STDOUT,
4455c6b4c7Sopenharmony_ci    DUMP_TO_FILE,
4555c6b4c7Sopenharmony_ci    DUMP_REGION_TO_FILE
4655c6b4c7Sopenharmony_ci};
4755c6b4c7Sopenharmony_ci
4855c6b4c7Sopenharmony_cistruct MemDumpParam {
4955c6b4c7Sopenharmony_ci    enum MemDumpType type;
5055c6b4c7Sopenharmony_ci    unsigned long long start;
5155c6b4c7Sopenharmony_ci    unsigned long long size;
5255c6b4c7Sopenharmony_ci    char filePath[PATH_MAX_LEN];
5355c6b4c7Sopenharmony_ci};
5455c6b4c7Sopenharmony_ci
5555c6b4c7Sopenharmony_ci#define HIDUMPER_IOC_BASE            'd'
5655c6b4c7Sopenharmony_ci#define HIDUMPER_DUMP_ALL            _IO(HIDUMPER_IOC_BASE, 1)
5755c6b4c7Sopenharmony_ci#define HIDUMPER_CPU_USAGE           _IO(HIDUMPER_IOC_BASE, 2)
5855c6b4c7Sopenharmony_ci#define HIDUMPER_MEM_USAGE           _IO(HIDUMPER_IOC_BASE, 3)
5955c6b4c7Sopenharmony_ci#define HIDUMPER_TASK_INFO           _IO(HIDUMPER_IOC_BASE, 4)
6055c6b4c7Sopenharmony_ci#define HIDUMPER_INJECT_KERNEL_CRASH _IO(HIDUMPER_IOC_BASE, 5)
6155c6b4c7Sopenharmony_ci#define HIDUMPER_DUMP_FAULT_LOG      _IO(HIDUMPER_IOC_BASE, 6)
6255c6b4c7Sopenharmony_ci#define HIDUMPER_MEM_DATA            _IOW(HIDUMPER_IOC_BASE, 7, struct MemDumpParam)
6355c6b4c7Sopenharmony_ci
6455c6b4c7Sopenharmony_cistatic void Usage(void)
6555c6b4c7Sopenharmony_ci{
6655c6b4c7Sopenharmony_ci    printf("Usage:\n"
6755c6b4c7Sopenharmony_ci        "    hidumper                              dump cpu usage, memory usage and all tasks.\n"
6855c6b4c7Sopenharmony_ci        "or:\n"
6955c6b4c7Sopenharmony_ci        "    hidumper -dc                          dump the cpu usage.\n"
7055c6b4c7Sopenharmony_ci        "    hidumper -df                          dump the fault logs.\n"
7155c6b4c7Sopenharmony_ci        "    hidumper -dm                          dump the memory usage.\n"
7255c6b4c7Sopenharmony_ci        "    hidumper -dt                          dump all the tasks.\n"
7355c6b4c7Sopenharmony_ci        "    hidumper -h                           help text for the tool.\n"
7455c6b4c7Sopenharmony_ci        "    hidumper -ikc                         inject kernel crash for debug version.\n"
7555c6b4c7Sopenharmony_ci        "    hidumper -iuc                         inject user crash for debug version.\n");
7655c6b4c7Sopenharmony_ci    printf("    hidumper -m                           dump memory to stdout in hex format for debug version.\n"
7755c6b4c7Sopenharmony_ci        "    hidumper -m filepath                  dump memory to filepath in the device in hex format for "
7855c6b4c7Sopenharmony_ci        "debug version.\n"
7955c6b4c7Sopenharmony_ci        "    hidumper -m memstart memsize          dump memory with starting address memstart(hex) and\n"
8055c6b4c7Sopenharmony_ci        "                                          size memsize(hex) to stdout in hex format for debug version.\n"
8155c6b4c7Sopenharmony_ci        "    hidumper -m memstart memsize filepath dump memory with starting address memstart(hex) and\n"
8255c6b4c7Sopenharmony_ci        "                                          size memsize(hex) to filepath in hex format for debug version.\n");
8355c6b4c7Sopenharmony_ci}
8455c6b4c7Sopenharmony_ci
8555c6b4c7Sopenharmony_cistatic void ExecAction(int fd, unsigned int cmd)
8655c6b4c7Sopenharmony_ci{
8755c6b4c7Sopenharmony_ci    if (fd < 0) {
8855c6b4c7Sopenharmony_ci        printf("Invalid fd: %d\n", fd);
8955c6b4c7Sopenharmony_ci        return;
9055c6b4c7Sopenharmony_ci    }
9155c6b4c7Sopenharmony_ci
9255c6b4c7Sopenharmony_ci    int ret = ioctl(fd, cmd, NULL);
9355c6b4c7Sopenharmony_ci    if (ret < 0) {
9455c6b4c7Sopenharmony_ci        printf("Failed to ioctl [%u], error [%s]\n", cmd, strerror(errno));
9555c6b4c7Sopenharmony_ci    }
9655c6b4c7Sopenharmony_ci}
9755c6b4c7Sopenharmony_ci
9855c6b4c7Sopenharmony_cistatic void DumpALLInfo(int fd)
9955c6b4c7Sopenharmony_ci{
10055c6b4c7Sopenharmony_ci    ExecAction(fd, HIDUMPER_DUMP_ALL);
10155c6b4c7Sopenharmony_ci}
10255c6b4c7Sopenharmony_ci
10355c6b4c7Sopenharmony_cistatic void DumpCpuUsage(int fd)
10455c6b4c7Sopenharmony_ci{
10555c6b4c7Sopenharmony_ci    ExecAction(fd, HIDUMPER_CPU_USAGE);
10655c6b4c7Sopenharmony_ci}
10755c6b4c7Sopenharmony_ci
10855c6b4c7Sopenharmony_cistatic void DumpMemUsage(int fd)
10955c6b4c7Sopenharmony_ci{
11055c6b4c7Sopenharmony_ci    ExecAction(fd, HIDUMPER_MEM_USAGE);
11155c6b4c7Sopenharmony_ci}
11255c6b4c7Sopenharmony_ci
11355c6b4c7Sopenharmony_cistatic void DumpTaskInfo(int fd)
11455c6b4c7Sopenharmony_ci{
11555c6b4c7Sopenharmony_ci    ExecAction(fd, HIDUMPER_TASK_INFO);
11655c6b4c7Sopenharmony_ci}
11755c6b4c7Sopenharmony_ci
11855c6b4c7Sopenharmony_cistatic void DumpMemData(int fd, struct MemDumpParam *param)
11955c6b4c7Sopenharmony_ci{
12055c6b4c7Sopenharmony_ci#ifdef OHOS_DEBUG
12155c6b4c7Sopenharmony_ci    int ret = ioctl(fd, HIDUMPER_MEM_DATA, param);
12255c6b4c7Sopenharmony_ci    if (ret < 0) {
12355c6b4c7Sopenharmony_ci        printf("Failed to ioctl [%s], error [%s]\n", HIDUMPER_DEVICE, strerror(errno));
12455c6b4c7Sopenharmony_ci    }
12555c6b4c7Sopenharmony_ci#else
12655c6b4c7Sopenharmony_ci    (void)fd;
12755c6b4c7Sopenharmony_ci    (void)param;
12855c6b4c7Sopenharmony_ci    printf("Unsupported!\n");
12955c6b4c7Sopenharmony_ci#endif
13055c6b4c7Sopenharmony_ci}
13155c6b4c7Sopenharmony_ci
13255c6b4c7Sopenharmony_cistatic void InjectKernelCrash(int fd)
13355c6b4c7Sopenharmony_ci{
13455c6b4c7Sopenharmony_ci#ifdef OHOS_DEBUG
13555c6b4c7Sopenharmony_ci    ExecAction(fd, HIDUMPER_INJECT_KERNEL_CRASH);
13655c6b4c7Sopenharmony_ci#else
13755c6b4c7Sopenharmony_ci    (void)fd;
13855c6b4c7Sopenharmony_ci    printf("Unsupported!\n");
13955c6b4c7Sopenharmony_ci#endif
14055c6b4c7Sopenharmony_ci}
14155c6b4c7Sopenharmony_ci
14255c6b4c7Sopenharmony_cistatic void DumpFaultLog(int fd)
14355c6b4c7Sopenharmony_ci{
14455c6b4c7Sopenharmony_ci    ExecAction(fd, HIDUMPER_DUMP_FAULT_LOG);
14555c6b4c7Sopenharmony_ci}
14655c6b4c7Sopenharmony_ci
14755c6b4c7Sopenharmony_cistatic void InjectUserCrash(void)
14855c6b4c7Sopenharmony_ci{
14955c6b4c7Sopenharmony_ci#ifdef OHOS_DEBUG
15055c6b4c7Sopenharmony_ci    *((int *)USER_FAULT_ADDR) = USER_FAULT_VALUE;
15155c6b4c7Sopenharmony_ci#else
15255c6b4c7Sopenharmony_ci    printf("Unsupported!\n");
15355c6b4c7Sopenharmony_ci#endif
15455c6b4c7Sopenharmony_ci}
15555c6b4c7Sopenharmony_ci
15655c6b4c7Sopenharmony_ciint ParameterMatching(int argc, const char *argv[], int fd)
15755c6b4c7Sopenharmony_ci{
15855c6b4c7Sopenharmony_ci    struct MemDumpParam param;
15955c6b4c7Sopenharmony_ci    if (argc == ONE_OF_ARGC_PARAMETERS) {
16055c6b4c7Sopenharmony_ci        DumpALLInfo(fd);
16155c6b4c7Sopenharmony_ci    } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-dc") == 0) {
16255c6b4c7Sopenharmony_ci        DumpCpuUsage(fd);
16355c6b4c7Sopenharmony_ci    } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-df") == 0) {
16455c6b4c7Sopenharmony_ci        DumpFaultLog(fd);
16555c6b4c7Sopenharmony_ci    } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-dm") == 0) {
16655c6b4c7Sopenharmony_ci        DumpMemUsage(fd);
16755c6b4c7Sopenharmony_ci    } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-dt") == 0) {
16855c6b4c7Sopenharmony_ci        DumpTaskInfo(fd);
16955c6b4c7Sopenharmony_ci    } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-ikc") == 0) {
17055c6b4c7Sopenharmony_ci        InjectKernelCrash(fd);
17155c6b4c7Sopenharmony_ci    } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-iuc") == 0) {
17255c6b4c7Sopenharmony_ci        InjectUserCrash();
17355c6b4c7Sopenharmony_ci    }  else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
17455c6b4c7Sopenharmony_ci        param.type = DUMP_TO_STDOUT;
17555c6b4c7Sopenharmony_ci        DumpMemData(fd, &param);
17655c6b4c7Sopenharmony_ci    } else if (argc == THREE_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
17755c6b4c7Sopenharmony_ci        param.type = DUMP_TO_FILE;
17855c6b4c7Sopenharmony_ci        if (strncpy_s(param.filePath, sizeof(param.filePath),
17955c6b4c7Sopenharmony_ci            argv[TWO_OF_ARGC_PARAMETERS], sizeof(param.filePath) - 1) != EOK) {
18055c6b4c7Sopenharmony_ci            printf("param.filePath is not enough or strncpy_s failed\n");
18155c6b4c7Sopenharmony_ci            return -1;
18255c6b4c7Sopenharmony_ci        }
18355c6b4c7Sopenharmony_ci        DumpMemData(fd, &param);
18455c6b4c7Sopenharmony_ci    } else if (argc == FOUR_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
18555c6b4c7Sopenharmony_ci        param.type = DUMP_TO_STDOUT;
18655c6b4c7Sopenharmony_ci        param.start = strtoull(argv[TWO_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
18755c6b4c7Sopenharmony_ci        param.size = strtoull(argv[THREE_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
18855c6b4c7Sopenharmony_ci        DumpMemData(fd, &param);
18955c6b4c7Sopenharmony_ci    }  else if (argc == FIVE_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
19055c6b4c7Sopenharmony_ci        param.type = DUMP_TO_FILE;
19155c6b4c7Sopenharmony_ci        param.start = strtoull(argv[TWO_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
19255c6b4c7Sopenharmony_ci        param.size = strtoull(argv[THREE_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
19355c6b4c7Sopenharmony_ci        if (strncpy_s(param.filePath, sizeof(param.filePath),
19455c6b4c7Sopenharmony_ci            argv[FOUR_OF_ARGC_PARAMETERS], sizeof(param.filePath) - 1) != EOK) {
19555c6b4c7Sopenharmony_ci            printf("param.filePath is not enough or strncpy_s failed\n");
19655c6b4c7Sopenharmony_ci            return -1;
19755c6b4c7Sopenharmony_ci        }
19855c6b4c7Sopenharmony_ci        DumpMemData(fd, &param);
19955c6b4c7Sopenharmony_ci    } else {
20055c6b4c7Sopenharmony_ci        Usage();
20155c6b4c7Sopenharmony_ci    }
20255c6b4c7Sopenharmony_ci    return 0;
20355c6b4c7Sopenharmony_ci}
20455c6b4c7Sopenharmony_ci
20555c6b4c7Sopenharmony_ciint main(int argc, const char *argv[])
20655c6b4c7Sopenharmony_ci{
20755c6b4c7Sopenharmony_ci    int fd = -1;
20855c6b4c7Sopenharmony_ci    fd = open(HIDUMPER_DEVICE, O_RDONLY);
20955c6b4c7Sopenharmony_ci    if (fd < 0) {
21055c6b4c7Sopenharmony_ci        printf("Failed to open [%s], error [%s]\n", HIDUMPER_DEVICE, strerror(errno));
21155c6b4c7Sopenharmony_ci        return -1;
21255c6b4c7Sopenharmony_ci    }
21355c6b4c7Sopenharmony_ci
21455c6b4c7Sopenharmony_ci    int ret = ParameterMatching(argc, argv, fd);
21555c6b4c7Sopenharmony_ci    close(fd);
21655c6b4c7Sopenharmony_ci    return ret;
21755c6b4c7Sopenharmony_ci}
218