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