ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/mports/trunk/devel/gdb/files/kgdb/kgdb-main.c
Revision: 24716
Committed: Mon Nov 26 17:06:28 2018 UTC (5 years, 5 months ago) by laffer1
Content type: text/plain
File size: 10953 byte(s)
Log Message:
update gdb to 8.2

File Contents

# Content
1 /*
2 * Copyright (c) 2004 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: head/devel/gdb/files/kgdb/kgdb-main.c 480613 2018-09-24 17:23:35Z jhb $");
29
30 #include <sys/param.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34 #include <sys/resource.h>
35 #include <sys/select.h>
36 #include <sys/time.h>
37 #include <sys/wait.h>
38 #include <errno.h>
39 #include <err.h>
40 #include <kvm.h>
41 #include <limits.h>
42 #include <paths.h>
43
44 /* libgdb stuff. */
45 #include <defs.h>
46 #include <frame.h>
47 #include <frame-unwind.h>
48 #include <inferior.h>
49 #include <interps.h>
50 #include <cli-out.h>
51 #include <main.h>
52 #include <objfiles.h>
53 #include <target.h>
54 #include <top.h>
55 #include <ui-file.h>
56 #include <bfd.h>
57 #include <gdbcore.h>
58
59 #include <unistd.h>
60
61 #include "kgdb.h"
62
63 static int verbose;
64
65 static char crashdir[PATH_MAX];
66 static char *dumpnr;
67 static char *kernel;
68 static char *remote;
69 static char *vmcore;
70
71 /*
72 * TODO:
73 * - test remote kgdb (see if threads and klds work)
74 * - possibly split kthr.c out into a separate thread_stratum target that
75 * uses new_objfile test to push itself when a FreeBSD kernel is loaded
76 * (check for kernel osabi) (probably don't bother with this)
77 * + test alternate kgdb_lookup()
78 * + fix kgdb build on amd64 to include i386 cross-debug support
79 * - propose expanded libkvm interface that supports cross-debug and moves
80 * MD bits of kgdb into the library (examining PCB's and exporting a
81 * stable-ABI struct of registers, similarly for trapframe handling and
82 * stop-pcb stuff
83 * + use tid's as lwp IDs instead of PIDs in ptid's
84 */
85
86 static void
87 usage(void)
88 {
89
90 fprintf(stderr,
91 "usage: %s [-afqvw] [-b rate] [-d crashdir] [-c core | -n dumpnr | -r device]\n"
92 "\t[kernel [core]]\n", getprogname());
93 exit(1);
94 }
95
96 static void
97 kernel_from_dumpnr(const char *nr)
98 {
99 char line[PATH_MAX], path[PATH_MAX];
100 FILE *info;
101 char *dir;
102 struct stat st;
103 int l;
104
105 /*
106 * If there's a kernel image right here in the crash directory, then
107 * use it. The kernel image is either called kernel.<nr> or is in a
108 * subdirectory kernel.<nr> and called kernel. The latter allows us
109 * to collect the modules in the same place.
110 */
111 snprintf(path, sizeof(path), "%s/kernel.%s", crashdir, nr);
112 if (stat(path, &st) == 0) {
113 if (S_ISREG(st.st_mode)) {
114 kernel = strdup(path);
115 return;
116 }
117 if (S_ISDIR(st.st_mode)) {
118 snprintf(path, sizeof(path), "%s/kernel.%s/kernel",
119 crashdir, nr);
120 if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
121 kernel = strdup(path);
122 return;
123 }
124 }
125 }
126
127 /*
128 * No kernel image here. Parse the dump header. The kernel object
129 * directory can be found there and we probably have the kernel
130 * image still in it. The object directory may also have a kernel
131 * with debugging info (called either kernel.full or kernel.debug).
132 * If we have a debug kernel, use it.
133 */
134 snprintf(path, sizeof(path), "%s/info.%s", crashdir, nr);
135 info = fopen(path, "r");
136 if (info == NULL) {
137 warn("%s", path);
138 return;
139 }
140 while (fgets(line, sizeof(line), info) != NULL) {
141 l = strlen(line);
142 if (l > 0 && line[l - 1] == '\n')
143 line[--l] = '\0';
144 if (strncmp(line, " ", 4) == 0) {
145 fclose(info);
146 dir = strchr(line, ':');
147 dir = (dir == NULL) ? line + 4 : dir + 1;
148
149 /*
150 * Check for kernel.full first as if it exists
151 * kernel.debug will also exist, but will only
152 * contain debug symbols and not be recognized
153 * as a valid kernel by the osabi sniffer.
154 */
155 snprintf(path, sizeof(path), "%s/kernel.full", dir);
156 if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
157 kernel = strdup(path);
158 return;
159 }
160 snprintf(path, sizeof(path), "%s/kernel.debug", dir);
161 if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
162 kernel = strdup(path);
163 return;
164 }
165 snprintf(path, sizeof(path), "%s/kernel", dir);
166 if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
167 kernel = strdup(path);
168 return;
169 }
170 return;
171 }
172 }
173 fclose(info);
174 }
175
176 /*
177 * Remote targets can support any number of syntaxes and we want to
178 * support them all with one addition: we support specifying a device
179 * node for a serial device without the "/dev/" prefix.
180 *
181 * What we do is to stat(2) the existing remote target first. If that
182 * fails, we try it with "/dev/" prepended. If that succeeds we use
183 * the resulting path, otherwise we use the original target. If
184 * either stat(2) succeeds make sure the file is either a character
185 * device or a FIFO.
186 */
187 static void
188 verify_remote(void)
189 {
190 char path[PATH_MAX];
191 struct stat st;
192
193 if (stat(remote, &st) != 0) {
194 snprintf(path, sizeof(path), "/dev/%s", remote);
195 if (stat(path, &st) != 0)
196 return;
197 free(remote);
198 remote = strdup(path);
199 }
200 if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode))
201 errx(1, "%s: not a special file, FIFO or socket", remote);
202 }
203
204 static void
205 add_arg(struct captured_main_args *args, char const *arg)
206 {
207
208 args->argc++;
209 args->argv = (char **)reallocf(args->argv, (args->argc + 1) *
210 sizeof(char *));
211 if (args->argv == NULL)
212 err(1, "Out of memory building argument list");
213 args->argv[args->argc] = (char *)arg;
214 }
215
216 int
217 main(int argc, char *argv[])
218 {
219 char path[PATH_MAX];
220 struct stat st;
221 struct captured_main_args args;
222 char *s;
223 int a, ch, writeable;
224
225 dumpnr = NULL;
226 writeable = 0;
227
228 strlcpy(crashdir, "/var/crash", sizeof(crashdir));
229 s = getenv("KGDB_CRASH_DIR");
230 if (s != NULL)
231 strlcpy(crashdir, s, sizeof(crashdir));
232
233 /* Convert long options into short options. */
234 for (a = 1; a < argc; a++) {
235 s = argv[a];
236 if (s[0] == '-') {
237 s++;
238 /* Long options take either 1 or 2 dashes. */
239 if (s[0] == '-')
240 s++;
241 if (strcmp(s, "quiet") == 0)
242 argv[a] = (char *)"-q";
243 else if (strcmp(s, "fullname") == 0)
244 argv[a] = (char *)"-f";
245 }
246 }
247
248 kgdb_quiet = 0;
249 memset (&args, 0, sizeof args);
250 args.interpreter_p = INTERP_CONSOLE;
251 args.argv = (char **)xmalloc(sizeof(char *));
252 args.argv[0] = argv[0];
253
254 while ((ch = getopt(argc, argv, "ab:c:d:fn:qr:vw")) != -1) {
255 switch (ch) {
256 case 'a':
257 annotation_level++;
258 break;
259 case 'b': {
260 int i;
261 char *p;
262
263 i = strtol(optarg, &p, 0);
264 if (*p != '\0' || p == optarg)
265 warnx("warning: could not set baud rate to `%s'.\n",
266 optarg);
267 else
268 baud_rate = i;
269 break;
270 }
271 case 'c': /* use given core file. */
272 if (vmcore != NULL) {
273 warnx("option %c: can only be specified once",
274 optopt);
275 usage();
276 /* NOTREACHED */
277 }
278 vmcore = strdup(optarg);
279 break;
280 case 'd': /* lookup dumps in given directory. */
281 strlcpy(crashdir, optarg, sizeof(crashdir));
282 break;
283 case 'f':
284 annotation_level = 1;
285 break;
286 case 'n': /* use dump with given number. */
287 dumpnr = optarg;
288 break;
289 case 'q':
290 kgdb_quiet = 1;
291 add_arg(&args, "-q");
292 break;
293 case 'r': /* use given device for remote session. */
294 if (remote != NULL) {
295 warnx("option %c: can only be specified once",
296 optopt);
297 usage();
298 /* NOTREACHED */
299 }
300 remote = strdup(optarg);
301 break;
302 case 'v': /* increase verbosity. */
303 verbose++;
304 break;
305 case 'w': /* core file is writeable. */
306 writeable = 1;
307 break;
308 case '?':
309 default:
310 usage();
311 }
312 }
313
314 if (((vmcore != NULL) ? 1 : 0) + ((dumpnr != NULL) ? 1 : 0) +
315 ((remote != NULL) ? 1 : 0) > 1) {
316 warnx("options -c, -n and -r are mutually exclusive");
317 usage();
318 /* NOTREACHED */
319 }
320
321 if (verbose > 1)
322 warnx("using %s as the crash directory", crashdir);
323
324 if (argc > optind)
325 kernel = strdup(argv[optind++]);
326
327 if (argc > optind && (dumpnr != NULL || remote != NULL)) {
328 warnx("options -n and -r do not take a core file. Ignored");
329 optind = argc;
330 }
331
332 if (dumpnr != NULL) {
333 snprintf(path, sizeof(path), "%s/vmcore.%s", crashdir, dumpnr);
334 if (stat(path, &st) == -1)
335 err(1, "%s", path);
336 if (!S_ISREG(st.st_mode))
337 errx(1, "%s: not a regular file", path);
338 vmcore = strdup(path);
339 } else if (remote != NULL) {
340 verify_remote();
341 } else if (argc > optind) {
342 if (vmcore == NULL)
343 vmcore = strdup(argv[optind++]);
344 if (argc > optind)
345 warnx("multiple core files specified. Ignored");
346 } else if (vmcore == NULL && kernel == NULL) {
347 vmcore = strdup(_PATH_MEM);
348 kernel = strdup(getbootfile());
349 }
350
351 if (verbose) {
352 if (vmcore != NULL)
353 warnx("core file: %s", vmcore);
354 if (remote != NULL)
355 warnx("device file: %s", remote);
356 if (kernel != NULL)
357 warnx("kernel image: %s", kernel);
358 }
359
360 /* A remote target requires an explicit kernel argument. */
361 if (remote != NULL && kernel == NULL) {
362 warnx("remote debugging requires a kernel");
363 usage();
364 /* NOTREACHED */
365 }
366
367 /* If we don't have a kernel image yet, try to find one. */
368 if (kernel == NULL) {
369 if (dumpnr != NULL)
370 kernel_from_dumpnr(dumpnr);
371
372 if (kernel == NULL)
373 errx(1, "couldn't find a suitable kernel image");
374 if (verbose)
375 warnx("kernel image: %s", kernel);
376 }
377
378 /* Set an alternate prompt. */
379 add_arg(&args, "-iex");
380 add_arg(&args, "set prompt (kgdb) ");
381
382 /* Change osabi to assume a FreeBSD kernel. */
383 add_arg(&args, "-iex");
384 add_arg(&args, "set osabi FreeBSD/kernel");
385
386 /* Open the vmcore if requested. */
387 if (vmcore != NULL) {
388 add_arg(&args, "-ex");
389 if (asprintf(&s, "target vmcore %s%s", writeable ? "-w " : "",
390 vmcore) < 0)
391 err(1, "couldn't build command line");
392 add_arg(&args, s);
393 }
394
395 /* Open the remote target if requested. */
396 if (remote != NULL) {
397 add_arg(&args, "-ex");
398 if (asprintf(&s, "target remote %s", remote) < 0)
399 err(1, "couldn't build command line");
400 add_arg(&args, s);
401 }
402
403 add_arg(&args, kernel);
404
405 /* The libgdb code uses optind too. Reset it... */
406 optind = 0;
407
408 /* Terminate argv list. */
409 add_arg(&args, NULL);
410
411 return (gdb_main(&args));
412 }

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain