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