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, ¶m); 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, ¶m); 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, ¶m); 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, ¶m); 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