1 /*
2  * Copyright (c) 2020 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 
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 
22 #include <sys/ioctl.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 
26 #include "securec.h"
27 
28 #define HIDUMPER_DEVICE  "/dev/hidumper"
29 #define USER_FAULT_ADDR  0x3
30 #define USER_FAULT_VALUE 0x4
31 #define PATH_MAX_LEN     256
32 
33 #define ONE_OF_ARGC_PARAMETERS           1
34 #define TWO_OF_ARGC_PARAMETERS           2
35 #define THREE_OF_ARGC_PARAMETERS         3
36 #define FOUR_OF_ARGC_PARAMETERS          4
37 #define FIVE_OF_ARGC_PARAMETERS          5
38 
39 #define BUF_SIZE_16                      16
40 
41 enum MemDumpType {
42     DUMP_TO_STDOUT,
43     DUMP_REGION_TO_STDOUT,
44     DUMP_TO_FILE,
45     DUMP_REGION_TO_FILE
46 };
47 
48 struct MemDumpParam {
49     enum MemDumpType type;
50     unsigned long long start;
51     unsigned long long size;
52     char filePath[PATH_MAX_LEN];
53 };
54 
55 #define HIDUMPER_IOC_BASE            'd'
56 #define HIDUMPER_DUMP_ALL            _IO(HIDUMPER_IOC_BASE, 1)
57 #define HIDUMPER_CPU_USAGE           _IO(HIDUMPER_IOC_BASE, 2)
58 #define HIDUMPER_MEM_USAGE           _IO(HIDUMPER_IOC_BASE, 3)
59 #define HIDUMPER_TASK_INFO           _IO(HIDUMPER_IOC_BASE, 4)
60 #define HIDUMPER_INJECT_KERNEL_CRASH _IO(HIDUMPER_IOC_BASE, 5)
61 #define HIDUMPER_DUMP_FAULT_LOG      _IO(HIDUMPER_IOC_BASE, 6)
62 #define HIDUMPER_MEM_DATA            _IOW(HIDUMPER_IOC_BASE, 7, struct MemDumpParam)
63 
Usage(void)64 static void Usage(void)
65 {
66     printf("Usage:\n"
67         "    hidumper                              dump cpu usage, memory usage and all tasks.\n"
68         "or:\n"
69         "    hidumper -dc                          dump the cpu usage.\n"
70         "    hidumper -df                          dump the fault logs.\n"
71         "    hidumper -dm                          dump the memory usage.\n"
72         "    hidumper -dt                          dump all the tasks.\n"
73         "    hidumper -h                           help text for the tool.\n"
74         "    hidumper -ikc                         inject kernel crash for debug version.\n"
75         "    hidumper -iuc                         inject user crash for debug version.\n");
76     printf("    hidumper -m                           dump memory to stdout in hex format for debug version.\n"
77         "    hidumper -m filepath                  dump memory to filepath in the device in hex format for "
78         "debug version.\n"
79         "    hidumper -m memstart memsize          dump memory with starting address memstart(hex) and\n"
80         "                                          size memsize(hex) to stdout in hex format for debug version.\n"
81         "    hidumper -m memstart memsize filepath dump memory with starting address memstart(hex) and\n"
82         "                                          size memsize(hex) to filepath in hex format for debug version.\n");
83 }
84 
ExecAction(int fd,unsigned int cmd)85 static void ExecAction(int fd, unsigned int cmd)
86 {
87     if (fd < 0) {
88         printf("Invalid fd: %d\n", fd);
89         return;
90     }
91 
92     int ret = ioctl(fd, cmd, NULL);
93     if (ret < 0) {
94         printf("Failed to ioctl [%u], error [%s]\n", cmd, strerror(errno));
95     }
96 }
97 
DumpALLInfo(int fd)98 static void DumpALLInfo(int fd)
99 {
100     ExecAction(fd, HIDUMPER_DUMP_ALL);
101 }
102 
DumpCpuUsage(int fd)103 static void DumpCpuUsage(int fd)
104 {
105     ExecAction(fd, HIDUMPER_CPU_USAGE);
106 }
107 
DumpMemUsage(int fd)108 static void DumpMemUsage(int fd)
109 {
110     ExecAction(fd, HIDUMPER_MEM_USAGE);
111 }
112 
DumpTaskInfo(int fd)113 static void DumpTaskInfo(int fd)
114 {
115     ExecAction(fd, HIDUMPER_TASK_INFO);
116 }
117 
DumpMemData(int fd,struct MemDumpParam * param)118 static void DumpMemData(int fd, struct MemDumpParam *param)
119 {
120 #ifdef OHOS_DEBUG
121     int ret = ioctl(fd, HIDUMPER_MEM_DATA, param);
122     if (ret < 0) {
123         printf("Failed to ioctl [%s], error [%s]\n", HIDUMPER_DEVICE, strerror(errno));
124     }
125 #else
126     (void)fd;
127     (void)param;
128     printf("Unsupported!\n");
129 #endif
130 }
131 
InjectKernelCrash(int fd)132 static void InjectKernelCrash(int fd)
133 {
134 #ifdef OHOS_DEBUG
135     ExecAction(fd, HIDUMPER_INJECT_KERNEL_CRASH);
136 #else
137     (void)fd;
138     printf("Unsupported!\n");
139 #endif
140 }
141 
DumpFaultLog(int fd)142 static void DumpFaultLog(int fd)
143 {
144     ExecAction(fd, HIDUMPER_DUMP_FAULT_LOG);
145 }
146 
InjectUserCrash(void)147 static void InjectUserCrash(void)
148 {
149 #ifdef OHOS_DEBUG
150     *((int *)USER_FAULT_ADDR) = USER_FAULT_VALUE;
151 #else
152     printf("Unsupported!\n");
153 #endif
154 }
155 
ParameterMatching(int argc,const char * argv[],int fd)156 int ParameterMatching(int argc, const char *argv[], int fd)
157 {
158     struct MemDumpParam param;
159     if (argc == ONE_OF_ARGC_PARAMETERS) {
160         DumpALLInfo(fd);
161     } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-dc") == 0) {
162         DumpCpuUsage(fd);
163     } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-df") == 0) {
164         DumpFaultLog(fd);
165     } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-dm") == 0) {
166         DumpMemUsage(fd);
167     } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-dt") == 0) {
168         DumpTaskInfo(fd);
169     } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-ikc") == 0) {
170         InjectKernelCrash(fd);
171     } else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-iuc") == 0) {
172         InjectUserCrash();
173     }  else if (argc == TWO_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
174         param.type = DUMP_TO_STDOUT;
175         DumpMemData(fd, &param);
176     } else if (argc == THREE_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
177         param.type = DUMP_TO_FILE;
178         if (strncpy_s(param.filePath, sizeof(param.filePath),
179             argv[TWO_OF_ARGC_PARAMETERS], sizeof(param.filePath) - 1) != EOK) {
180             printf("param.filePath is not enough or strncpy_s failed\n");
181             return -1;
182         }
183         DumpMemData(fd, &param);
184     } else if (argc == FOUR_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
185         param.type = DUMP_TO_STDOUT;
186         param.start = strtoull(argv[TWO_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
187         param.size = strtoull(argv[THREE_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
188         DumpMemData(fd, &param);
189     }  else if (argc == FIVE_OF_ARGC_PARAMETERS && strcmp(argv[ONE_OF_ARGC_PARAMETERS], "-m") == 0) {
190         param.type = DUMP_TO_FILE;
191         param.start = strtoull(argv[TWO_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
192         param.size = strtoull(argv[THREE_OF_ARGC_PARAMETERS], NULL, BUF_SIZE_16);
193         if (strncpy_s(param.filePath, sizeof(param.filePath),
194             argv[FOUR_OF_ARGC_PARAMETERS], sizeof(param.filePath) - 1) != EOK) {
195             printf("param.filePath is not enough or strncpy_s failed\n");
196             return -1;
197         }
198         DumpMemData(fd, &param);
199     } else {
200         Usage();
201     }
202     return 0;
203 }
204 
main(int argc,const char * argv[])205 int main(int argc, const char *argv[])
206 {
207     int fd = -1;
208     fd = open(HIDUMPER_DEVICE, O_RDONLY);
209     if (fd < 0) {
210         printf("Failed to open [%s], error [%s]\n", HIDUMPER_DEVICE, strerror(errno));
211         return -1;
212     }
213 
214     int ret = ParameterMatching(argc, argv, fd);
215     close(fd);
216     return ret;
217 }
218