]>
Commit | Line | Data |
---|---|---|
d0e5dd3a JT |
1 | /* minidumper.cc |
2 | ||
3 | Copyright 2014 Red Hat Inc. | |
4 | ||
5 | This file is part of Cygwin. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License (file COPYING.dumper) for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | */ | |
21 | ||
22 | #include <sys/cygwin.h> | |
23 | #include <cygwin/version.h> | |
24 | #include <getopt.h> | |
25 | #include <errno.h> | |
26 | #include <stdio.h> | |
27 | #include <stdlib.h> | |
28 | #include <windows.h> | |
8f8e7757 | 29 | #include <dbghelp.h> |
d0e5dd3a JT |
30 | |
31 | BOOL verbose = FALSE; | |
32 | BOOL nokill = FALSE; | |
33 | ||
d0e5dd3a JT |
34 | static void |
35 | minidump(DWORD pid, MINIDUMP_TYPE dump_type, const char *minidump_file) | |
36 | { | |
37 | HANDLE dump_file; | |
38 | HANDLE process; | |
d0e5dd3a JT |
39 | |
40 | dump_file = CreateFile(minidump_file, | |
41 | GENERIC_READ | GENERIC_WRITE, | |
42 | 0, | |
43 | NULL, | |
44 | CREATE_ALWAYS, | |
45 | FILE_FLAG_BACKUP_SEMANTICS, | |
46 | NULL); | |
47 | if (dump_file == INVALID_HANDLE_VALUE) | |
48 | { | |
49 | fprintf (stderr, "error opening file\n"); | |
50 | return; | |
51 | } | |
52 | ||
53 | process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, | |
54 | FALSE, | |
55 | pid); | |
638f0ebf | 56 | if (process == NULL) |
d0e5dd3a JT |
57 | { |
58 | fprintf (stderr, "error opening process\n"); | |
59 | return; | |
60 | } | |
61 | ||
8f8e7757 JT |
62 | BOOL success = MiniDumpWriteDump(process, |
63 | pid, | |
64 | dump_file, | |
65 | dump_type, | |
66 | NULL, | |
67 | NULL, | |
68 | NULL); | |
d0e5dd3a JT |
69 | if (success) |
70 | { | |
71 | if (verbose) | |
72 | printf ("minidump created successfully\n"); | |
73 | } | |
74 | else | |
75 | { | |
76 | fprintf (stderr, "error creating minidump\n"); | |
77 | } | |
78 | ||
79 | /* Unless nokill is given, behave like dumper and terminate the dumped | |
80 | process */ | |
81 | if (!nokill) | |
82 | { | |
83 | TerminateProcess(process, 128 + 9); | |
84 | WaitForSingleObject(process, INFINITE); | |
85 | } | |
86 | ||
87 | CloseHandle(process); | |
88 | CloseHandle(dump_file); | |
d0e5dd3a JT |
89 | } |
90 | ||
91 | static void | |
92 | usage (FILE *stream, int status) | |
93 | { | |
94 | fprintf (stream, "\ | |
95 | Usage: %s [OPTION] FILENAME WIN32PID\n\ | |
96 | \n\ | |
97 | Write minidump from WIN32PID to FILENAME.dmp\n\ | |
98 | \n\ | |
99 | -t, --type minidump type flags\n\ | |
100 | -n, --nokill don't terminate the dumped process\n\ | |
101 | -d, --verbose be verbose while dumping\n\ | |
102 | -h, --help output help information and exit\n\ | |
103 | -q, --quiet be quiet while dumping (default)\n\ | |
104 | -V, --version output version information and exit\n\ | |
105 | \n", program_invocation_short_name); | |
106 | exit (status); | |
107 | } | |
108 | ||
109 | struct option longopts[] = { | |
110 | {"type", required_argument, NULL, 't'}, | |
111 | {"nokill", no_argument, NULL, 'n'}, | |
112 | {"verbose", no_argument, NULL, 'd'}, | |
113 | {"help", no_argument, NULL, 'h'}, | |
114 | {"quiet", no_argument, NULL, 'q'}, | |
115 | {"version", no_argument, 0, 'V'}, | |
116 | {0, no_argument, NULL, 0} | |
117 | }; | |
bdcad00b | 118 | const char *opts = "t:ndhqV"; |
d0e5dd3a JT |
119 | |
120 | static void | |
121 | print_version () | |
122 | { | |
123 | printf ("minidumper (cygwin) %d.%d.%d\n" | |
124 | "Minidump write for Cygwin\n" | |
125 | "Copyright (C) 1999 - %s Red Hat, Inc.\n" | |
126 | "This is free software; see the source for copying conditions. There is NO\n" | |
127 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", | |
128 | CYGWIN_VERSION_DLL_MAJOR / 1000, | |
129 | CYGWIN_VERSION_DLL_MAJOR % 1000, | |
130 | CYGWIN_VERSION_DLL_MINOR, | |
131 | strrchr (__DATE__, ' ') + 1); | |
132 | } | |
133 | ||
134 | int | |
135 | main (int argc, char **argv) | |
136 | { | |
137 | int opt; | |
138 | const char *p = ""; | |
139 | DWORD pid; | |
8f8e7757 | 140 | MINIDUMP_TYPE dump_type = MiniDumpNormal; |
d0e5dd3a JT |
141 | |
142 | while ((opt = getopt_long (argc, argv, opts, longopts, NULL) ) != EOF) | |
143 | switch (opt) | |
144 | { | |
145 | case 't': | |
146 | { | |
147 | char *endptr; | |
8f8e7757 | 148 | dump_type = (MINIDUMP_TYPE)strtoul(optarg, &endptr, 0); |
d0e5dd3a JT |
149 | if (*endptr != '\0') |
150 | { | |
151 | fprintf (stderr, "syntax error in minidump type \"%s\" near character #%d.\n", optarg, (int) (endptr - optarg)); | |
152 | exit(1); | |
153 | } | |
154 | } | |
155 | break; | |
156 | case 'n': | |
157 | nokill = TRUE; | |
158 | break; | |
159 | case 'd': | |
160 | verbose = TRUE; | |
161 | break; | |
162 | case 'q': | |
163 | verbose = FALSE; | |
164 | break; | |
165 | case 'h': | |
166 | usage (stdout, 0); | |
167 | case 'V': | |
168 | print_version (); | |
169 | exit (0); | |
170 | default: | |
171 | fprintf (stderr, "Try `%s --help' for more information.\n", | |
172 | program_invocation_short_name); | |
173 | exit (1); | |
174 | } | |
175 | ||
176 | if (argv && *(argv + optind) && *(argv + optind +1)) | |
177 | { | |
178 | ssize_t len = cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, | |
179 | *(argv + optind), NULL, 0); | |
180 | char *win32_name = (char *) alloca (len); | |
181 | cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, *(argv + optind), | |
182 | win32_name, len); | |
183 | if ((p = strrchr (win32_name, '\\'))) | |
184 | p++; | |
185 | else | |
186 | p = win32_name; | |
187 | ||
188 | pid = strtoul (*(argv + optind + 1), NULL, 10); | |
189 | } | |
190 | else | |
191 | { | |
192 | usage (stderr, 1); | |
193 | return -1; | |
194 | } | |
195 | ||
196 | char *minidump_file = (char *) malloc (strlen (p) + sizeof (".dmp")); | |
197 | if (!minidump_file) | |
198 | { | |
199 | fprintf (stderr, "error allocating memory\n"); | |
200 | return -1; | |
201 | } | |
202 | sprintf (minidump_file, "%s.dmp", p); | |
203 | ||
204 | if (verbose) | |
205 | printf ("dumping process %u to %s using dump type flags 0x%x\n", (unsigned int)pid, minidump_file, (unsigned int)dump_type); | |
206 | ||
207 | minidump(pid, dump_type, minidump_file); | |
208 | ||
209 | free (minidump_file); | |
210 | }; |