main.c revision 175808
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/gnu/usr.bin/gdb/kgdb/main.c 175808 2008-01-29 23:37:59Z 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 <fcntl.h>
41#include <inttypes.h>
42#include <kvm.h>
43#include <limits.h>
44#include <paths.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49
50/* libgdb stuff. */
51#include <defs.h>
52#include <frame.h>
53#include <frame-unwind.h>
54#include <inferior.h>
55#include <interps.h>
56#include <cli-out.h>
57#include <main.h>
58#include <target.h>
59#include <top.h>
60#include <bfd.h>
61#include <gdbcore.h>
62
63extern void (*init_ui_hook)(char *);
64
65extern frame_unwind_sniffer_ftype *kgdb_sniffer_kluge;
66
67extern void symbol_file_add_main (char *args, int from_tty);
68
69#include "kgdb.h"
70
71kvm_t *kvm;
72static char kvm_err[_POSIX2_LINE_MAX];
73
74static int dumpnr;
75static int quiet;
76static int verbose;
77
78static char crashdir[PATH_MAX];
79char *kernel;
80static char *remote;
81static char *vmcore;
82
83static void (*kgdb_new_objfile_chain)(struct objfile * objfile);
84
85static void
86kgdb_atexit(void)
87{
88	if (kvm != NULL)
89		kvm_close(kvm);
90}
91
92static void
93usage(void)
94{
95
96	fprintf(stderr,
97	    "usage: %s [-afqv] [-d crashdir] [-c core | -n dumpnr | -r device]\n"
98	    "\t[kernel [core]]\n", getprogname());
99	exit(1);
100}
101
102static void
103kernel_from_dumpnr(int nr)
104{
105	char path[PATH_MAX];
106	FILE *info;
107	char *s;
108	struct stat st;
109	int l;
110
111	/*
112	 * If there's a kernel image right here in the crash directory, then
113	 * use it.  The kernel image is either called kernel.<nr> or is in a
114	 * subdirectory kernel.<nr> and called kernel.  The latter allows us
115	 * to collect the modules in the same place.
116	 */
117	snprintf(path, sizeof(path), "%s/kernel.%d", crashdir, nr);
118	if (stat(path, &st) == 0) {
119		if (S_ISREG(st.st_mode)) {
120			kernel = strdup(path);
121			return;
122		}
123		if (S_ISDIR(st.st_mode)) {
124			snprintf(path, sizeof(path), "%s/kernel.%d/kernel",
125			    crashdir, nr);
126			if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
127				kernel = strdup(path);
128				return;
129			}
130		}
131	}
132
133	/*
134	 * No kernel image here.  Parse the dump header.  The kernel object
135	 * directory can be found there and we probably have the kernel
136	 * image still in it.  The object directory may also have a kernel
137	 * with debugging info (called kernel.debug).  If we have a debug
138	 * kernel, use it.
139	 */
140	snprintf(path, sizeof(path), "%s/info.%d", crashdir, nr);
141	info = fopen(path, "r");
142	if (info == NULL) {
143		warn(path);
144		return;
145	}
146	while (fgets(path, sizeof(path), info) != NULL) {
147		l = strlen(path);
148		if (l > 0 && path[l - 1] == '\n')
149			path[--l] = '\0';
150		if (strncmp(path, "    ", 4) == 0) {
151			s = strchr(path, ':');
152			s = (s == NULL) ? path + 4 : s + 1;
153			l = snprintf(path, sizeof(path), "%s/kernel.debug", s);
154			if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) {
155				path[l - 6] = '\0';
156				if (stat(path, &st) == -1 ||
157				    !S_ISREG(st.st_mode))
158					break;
159			}
160			kernel = strdup(path);
161			break;
162		}
163	}
164	fclose(info);
165}
166
167static void
168kgdb_new_objfile(struct objfile *objfile)
169{
170#if 0
171	printf("XXX: %s(%p)\n", __func__, objfile);
172	if (objfile != NULL) {
173		goto out;
174	}
175
176out:
177#endif
178	if (kgdb_new_objfile_chain != NULL)
179		kgdb_new_objfile_chain(objfile);
180}
181
182CORE_ADDR
183kgdb_parse(const char *exp)
184{
185	struct cleanup *old_chain;
186	struct expression *expr;
187	struct value *val;
188	char *s;
189	CORE_ADDR n;
190
191	s = strdup(exp);
192	old_chain = make_cleanup(free_current_contents, &expr);
193	expr = parse_expression(s);
194	val = (expr != NULL) ? evaluate_expression(expr) : NULL;
195	n = (val != NULL) ? value_as_address(val) : 0;
196	do_cleanups(old_chain);
197	free(s);
198	return (n);
199}
200
201#define	MSGBUF_SEQ_TO_POS(size, seq)	((seq) % (size))
202
203static void
204kgdb_init_target(void)
205{
206	CORE_ADDR bufp;
207	int size, rseq, wseq;
208	int kern_desc;
209	char c;
210
211	kern_desc = open(kernel, O_RDONLY);
212	if (kern_desc == -1)
213		errx(1, "couldn't open a kernel image");
214
215	kern_bfd = bfd_fdopenr(kernel, gnutarget, kern_desc);
216	if (kern_bfd == NULL) {
217		close(kern_desc);
218		errx(1, "\"%s\": can't open to probe ABI: %s.", kernel,
219			bfd_errmsg (bfd_get_error ()));
220	}
221	bfd_set_cacheable(kern_bfd, 1);
222
223	if (!bfd_check_format (kern_bfd, bfd_object)) {
224		bfd_close(kern_bfd);
225		errx(1, "\"%s\": not in executable format: %s", kernel,
226			bfd_errmsg(bfd_get_error()));
227        }
228
229	set_gdbarch_from_file (kern_bfd);
230
231	symbol_file_add_main (kernel, 0);
232	if (remote)
233		push_remote_target (remote, 0);
234	else
235		kgdb_target();
236
237	/*
238	 * Display the unread portion of the message buffer. This gives the
239	 * user a some initial data to work from.
240	 */
241	if (quiet)
242		return;
243	bufp = kgdb_parse("msgbufp->msg_ptr");
244	size = (int)kgdb_parse("msgbufp->msg_size");
245	rseq = (int)kgdb_parse("msgbufp->msg_rseq");
246	wseq = (int)kgdb_parse("msgbufp->msg_wseq");
247	rseq = MSGBUF_SEQ_TO_POS(size, rseq);
248	wseq = MSGBUF_SEQ_TO_POS(size, wseq);
249	if (bufp == 0 || size == 0 || rseq == wseq)
250		return;
251
252	printf("\nUnread portion of the kernel message buffer:\n");
253	while (rseq < wseq) {
254		read_memory(bufp + rseq, &c, 1);
255		putchar(c);
256		rseq++;
257		if (rseq == size)
258			rseq = 0;
259	}
260	if (c != '\n')
261		putchar('\n');
262	putchar('\n');
263}
264
265static void
266kgdb_interp_command_loop(void *data)
267{
268	static int once = 0;
269
270	if (!once) {
271		once = 1;
272		kgdb_init_target();
273		print_stack_frame(get_selected_frame(),
274		    frame_relative_level(get_selected_frame()), 1);
275	}
276	command_loop();
277}
278
279static void
280kgdb_init(char *argv0 __unused)
281{
282	static struct interp_procs procs = {
283		NULL,
284		NULL,
285		NULL,
286		NULL,
287		NULL,
288		kgdb_interp_command_loop
289	};
290	struct interp *kgdb;
291	kgdb = interp_new("kgdb", NULL, cli_out_new(gdb_stdout), &procs);
292	interp_add(kgdb);
293
294	set_prompt("(kgdb) ");
295	kgdb_new_objfile_chain = target_new_objfile_hook;
296	target_new_objfile_hook = kgdb_new_objfile;
297}
298
299int
300main(int argc, char *argv[])
301{
302	char path[PATH_MAX];
303	struct stat st;
304	struct captured_main_args args;
305	char *s;
306	int a, ch, writecore;
307
308	dumpnr = -1;
309
310	strlcpy(crashdir, "/var/crash", sizeof(crashdir));
311	s = getenv("KGDB_CRASH_DIR");
312	if (s != NULL)
313		strlcpy(crashdir, s, sizeof(crashdir));
314
315	/* Convert long options into short options. */
316	for (a = 1; a < argc; a++) {
317		s = argv[a];
318		if (s[0] == '-') {
319			s++;
320			/* Long options take either 1 or 2 dashes. */
321			if (s[0] == '-')
322				s++;
323			if (strcmp(s, "quiet") == 0)
324				argv[a] = "-q";
325			else if (strcmp(s, "fullname") == 0)
326				argv[a] = "-f";
327		}
328	}
329
330	quiet = 0;
331	writecore = 0;
332
333	while ((ch = getopt(argc, argv, "ac:d:fn:qr:vw")) != -1) {
334		switch (ch) {
335		case 'a':
336			annotation_level++;
337			break;
338		case 'c':	/* use given core file. */
339			if (vmcore != NULL) {
340				warnx("option %c: can only be specified once",
341				    optopt);
342				usage();
343				/* NOTREACHED */
344			}
345			vmcore = strdup(optarg);
346			break;
347		case 'd':	/* lookup dumps in given directory. */
348			strlcpy(crashdir, optarg, sizeof(crashdir));
349			break;
350		case 'f':
351			annotation_level = 1;
352			break;
353		case 'n':	/* use dump with given number. */
354			dumpnr = strtol(optarg, &s, 0);
355			if (dumpnr < 0 || *s != '\0') {
356				warnx("option %c: invalid kernel dump number",
357				    optopt);
358				usage();
359				/* NOTREACHED */
360			}
361			break;
362		case 'q':
363			quiet = 1;
364			break;
365		case 'r':	/* use given device for remote session. */
366			if (remote != NULL) {
367				warnx("option %c: can only be specified once",
368				    optopt);
369				usage();
370				/* NOTREACHED */
371			}
372			remote = strdup(optarg);
373			break;
374		case 'v':	/* increase verbosity. */
375			verbose++;
376			break;
377		case 'w':	/* core file is writeable. */
378			writecore = 1;
379			break;
380		case '?':
381		default:
382			usage();
383		}
384	}
385
386	if (((vmcore != NULL) ? 1 : 0) + ((dumpnr >= 0) ? 1 : 0) +
387	    ((remote != NULL) ? 1 : 0) > 1) {
388		warnx("options -c, -n and -r are mutually exclusive");
389		usage();
390		/* NOTREACHED */
391	}
392
393	if (verbose > 1)
394		warnx("using %s as the crash directory", crashdir);
395
396	if (argc > optind)
397		kernel = strdup(argv[optind++]);
398
399	if (argc > optind && (dumpnr >= 0 || remote != NULL)) {
400		warnx("options -n and -r do not take a core file. Ignored");
401		optind = argc;
402	}
403
404	if (dumpnr >= 0) {
405		snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr);
406		if (stat(path, &st) == -1)
407			err(1, path);
408		if (!S_ISREG(st.st_mode))
409			errx(1, "%s: not a regular file", path);
410		vmcore = strdup(path);
411	} else if (remote != NULL && remote[0] != ':' && remote[0] != '|') {
412		if (stat(remote, &st) != 0) {
413			snprintf(path, sizeof(path), "/dev/%s", remote);
414			if (stat(path, &st) != 0) {
415				err(1, "%s", remote);
416				/* NOTREACHED */
417			}
418			free(remote);
419			remote = strdup(path);
420		}
421		if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) {
422			errx(1, "%s: not a special file, FIFO or socket",
423			    remote);
424			/* NOTREACHED */
425		}
426	} else if (argc > optind) {
427		if (vmcore == NULL)
428			vmcore = strdup(argv[optind++]);
429		if (argc > optind)
430			warnx("multiple core files specified. Ignored");
431	} else if (vmcore == NULL && kernel == NULL) {
432		vmcore = strdup(_PATH_MEM);
433		kernel = strdup(getbootfile());
434	}
435
436	if (verbose) {
437		if (vmcore != NULL)
438			warnx("core file: %s", vmcore);
439		if (remote != NULL)
440			warnx("device file: %s", remote);
441		if (kernel != NULL)
442			warnx("kernel image: %s", kernel);
443	}
444
445	/*
446	 * At this point we must either have a core file or have a kernel
447	 * with a remote target.
448	 */
449	if (remote != NULL && kernel == NULL) {
450		warnx("remote debugging requires a kernel");
451		usage();
452		/* NOTREACHED */
453	}
454	if (vmcore == NULL && remote == NULL) {
455		warnx("need a core file or a device for remote debugging");
456		usage();
457		/* NOTREACHED */
458	}
459
460	/* If we don't have a kernel image yet, try to find one. */
461	if (kernel == NULL) {
462		if (dumpnr >= 0)
463			kernel_from_dumpnr(dumpnr);
464
465		if (kernel == NULL)
466			errx(1, "couldn't find a suitable kernel image");
467		if (verbose)
468			warnx("kernel image: %s", kernel);
469	}
470
471	if (remote == NULL) {
472		kvm = kvm_openfiles(kernel, vmcore, NULL,
473		    writecore ? O_RDWR : O_RDONLY, kvm_err);
474		if (kvm == NULL)
475			errx(1, kvm_err);
476		atexit(kgdb_atexit);
477		kgdb_thr_init();
478	}
479
480	/* The libgdb code uses optind too. Reset it... */
481	optind = 0;
482
483	memset (&args, 0, sizeof args);
484	args.argv = argv;
485	args.argc = 1 + quiet;
486	if (quiet)
487		argv[1] = "-q";
488	argv[args.argc] = NULL;
489	args.use_windows = 0;
490	args.interpreter_p = "kgdb";
491
492	init_ui_hook = kgdb_init;
493
494	kgdb_sniffer_kluge = kgdb_trgt_trapframe_sniffer;
495
496	return (gdb_main(&args));
497}
498