main.c revision 178670
1176349Smarcel/* 2176349Smarcel * Copyright (c) 2004 Marcel Moolenaar 3182724Sraj * All rights reserved. 4182724Sraj * 5176349Smarcel * Redistribution and use in source and binary forms, with or without 6176349Smarcel * modification, are permitted provided that the following conditions 7176349Smarcel * are met: 8176349Smarcel * 9176349Smarcel * 1. Redistributions of source code must retain the above copyright 10176349Smarcel * notice, this list of conditions and the following disclaimer. 11176349Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12176349Smarcel * notice, this list of conditions and the following disclaimer in the 13176349Smarcel * documentation and/or other materials provided with the distribution. 14176349Smarcel * 15176349Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16176349Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17176349Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18176349Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19176349Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20176349Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21176349Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22176349Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23176349Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24176349Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25176349Smarcel */ 26176349Smarcel 27176349Smarcel#include <sys/cdefs.h> 28176349Smarcel__FBSDID("$FreeBSD: head/gnu/usr.bin/gdb/kgdb/main.c 178670 2008-04-29 20:32:45Z jhb $"); 29176349Smarcel 30176349Smarcel#include <sys/param.h> 31176349Smarcel#include <sys/stat.h> 32176349Smarcel#include <sys/types.h> 33176349Smarcel#include <sys/ioctl.h> 34176349Smarcel#include <sys/resource.h> 35176349Smarcel#include <sys/select.h> 36176349Smarcel#include <sys/time.h> 37176349Smarcel#include <sys/wait.h> 38176349Smarcel#include <errno.h> 39176349Smarcel#include <err.h> 40176349Smarcel#include <inttypes.h> 41176349Smarcel#include <kvm.h> 42176487Smarcel#include <limits.h> 43176349Smarcel#include <paths.h> 44208538Sraj#include <stdio.h> 45243693Sgonzo#include <stdlib.h> 46208538Sraj#include <string.h> 47208538Sraj#include <unistd.h> 48176349Smarcel 49176349Smarcel/* libgdb stuff. */ 50176349Smarcel#include <defs.h> 51176349Smarcel#include <frame.h> 52176489Smarcel#include <frame-unwind.h> 53176349Smarcel#include <inferior.h> 54176489Smarcel#include <interps.h> 55176489Smarcel#include <cli-out.h> 56176349Smarcel#include <main.h> 57176489Smarcel#include <objfiles.h> 58176489Smarcel#include <target.h> 59176489Smarcel#include <top.h> 60176489Smarcel#include <ui-file.h> 61176489Smarcel#include <bfd.h> 62176489Smarcel#include <gdbcore.h> 63176489Smarcel#include <wrapper.h> 64176489Smarcel 65176489Smarcelextern frame_unwind_sniffer_ftype *kgdb_sniffer_kluge; 66176489Smarcel 67176489Smarcel#include "kgdb.h" 68176489Smarcel 69176349Smarcelstatic int dumpnr; 70176349Smarcelstatic int quiet; 71176487Smarcelstatic int verbose; 72176349Smarcel 73176349Smarcelstatic char crashdir[PATH_MAX]; 74176489Smarcelstatic char *kernel; 75235094Skientzlestatic char *remote; 76176489Smarcelstatic char *vmcore; 77176489Smarcelstatic struct ui_file *parse_gdberr; 78176489Smarcel 79176489Smarcelstatic void (*kgdb_new_objfile_chain)(struct objfile * objfile); 80176489Smarcel 81176489Smarcelstatic void 82176489Smarcelusage(void) 83176489Smarcel{ 84176489Smarcel 85176489Smarcel fprintf(stderr, 86176489Smarcel "usage: %s [-afqv] [-d crashdir] [-c core | -n dumpnr | -r device]\n" 87176489Smarcel "\t[kernel [core]]\n", getprogname()); 88176489Smarcel exit(1); 89176489Smarcel} 90176489Smarcel 91176489Smarcelstatic void 92176489Smarcelkernel_from_dumpnr(int nr) 93176489Smarcel{ 94176489Smarcel char path[PATH_MAX]; 95176489Smarcel FILE *info; 96176489Smarcel char *s; 97176489Smarcel struct stat st; 98176489Smarcel int l; 99176489Smarcel 100176489Smarcel /* 101176489Smarcel * If there's a kernel image right here in the crash directory, then 102176489Smarcel * use it. The kernel image is either called kernel.<nr> or is in a 103176489Smarcel * subdirectory kernel.<nr> and called kernel. The latter allows us 104176489Smarcel * to collect the modules in the same place. 105176489Smarcel */ 106176489Smarcel snprintf(path, sizeof(path), "%s/kernel.%d", crashdir, nr); 107176489Smarcel if (stat(path, &st) == 0) { 108176489Smarcel if (S_ISREG(st.st_mode)) { 109176489Smarcel kernel = strdup(path); 110176489Smarcel return; 111176489Smarcel } 112176489Smarcel if (S_ISDIR(st.st_mode)) { 113176489Smarcel snprintf(path, sizeof(path), "%s/kernel.%d/kernel", 114176489Smarcel crashdir, nr); 115176489Smarcel if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { 116176489Smarcel kernel = strdup(path); 117176489Smarcel return; 118176489Smarcel } 119176489Smarcel } 120176489Smarcel } 121176489Smarcel 122176489Smarcel /* 123176489Smarcel * No kernel image here. Parse the dump header. The kernel object 124176489Smarcel * directory can be found there and we probably have the kernel 125176489Smarcel * image still in it. The object directory may also have a kernel 126176489Smarcel * with debugging info (called kernel.debug). If we have a debug 127176489Smarcel * kernel, use it. 128176349Smarcel */ 129176349Smarcel snprintf(path, sizeof(path), "%s/info.%d", crashdir, nr); 130176489Smarcel info = fopen(path, "r"); 131176489Smarcel if (info == NULL) { 132176489Smarcel warn(path); 133176489Smarcel return; 134176489Smarcel } 135176489Smarcel while (fgets(path, sizeof(path), info) != NULL) { 136235094Skientzle l = strlen(path); 137235094Skientzle if (l > 0 && path[l - 1] == '\n') 138235094Skientzle path[--l] = '\0'; 139235094Skientzle if (strncmp(path, " ", 4) == 0) { 140235094Skientzle s = strchr(path, ':'); 141235094Skientzle s = (s == NULL) ? path + 4 : s + 1; 142176489Smarcel l = snprintf(path, sizeof(path), "%s/kernel.debug", s); 143176489Smarcel if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { 144176349Smarcel path[l - 6] = '\0'; 145176349Smarcel if (stat(path, &st) == -1 || 146176349Smarcel !S_ISREG(st.st_mode)) 147176349Smarcel break; 148176349Smarcel } 149176349Smarcel kernel = strdup(path); 150176349Smarcel break; 151176487Smarcel } 152176349Smarcel } 153176349Smarcel fclose(info); 154176489Smarcel} 155176489Smarcel 156176489Smarcelstatic void 157176489Smarcelkgdb_new_objfile(struct objfile *objfile) 158176489Smarcel{ 159176489Smarcel static int once = 1; 160176489Smarcel 161176489Smarcel kld_new_objfile(objfile); 162176489Smarcel kgdb_trgt_new_objfile(objfile); 163176489Smarcel 164176489Smarcel if (kgdb_new_objfile_chain != NULL) 165176489Smarcel kgdb_new_objfile_chain(objfile); 166176489Smarcel 167176489Smarcel if (once && objfile != NULL && objfile == symfile_objfile) { 168176489Smarcel /* 169176349Smarcel * The initial kernel has just been loaded. Start the 170176349Smarcel * remote target if we have one. 171176349Smarcel */ 172176489Smarcel once = 0; 173176349Smarcel if (remote != NULL) 174176349Smarcel push_remote_target (remote, 0); 175176349Smarcel } 176176349Smarcel} 177176349Smarcel 178176349Smarcel/* 179176349Smarcel * Parse an expression and return its value. If 'quiet' is true, then 180176349Smarcel * any error messages from the parser are masked. 181176349Smarcel */ 182176349SmarcelCORE_ADDR 183176349Smarcelkgdb_parse_1(const char *exp, int quiet) 184176349Smarcel{ 185176349Smarcel struct ui_file *old_stderr; 186176349Smarcel struct cleanup *old_chain; 187176349Smarcel struct expression *expr; 188176349Smarcel struct value *val; 189176349Smarcel char *s; 190176349Smarcel CORE_ADDR n; 191176489Smarcel 192176349Smarcel old_stderr = gdb_stderr; 193176349Smarcel if (quiet) 194176489Smarcel gdb_stderr = parse_gdberr; 195176349Smarcel n = 0; 196176349Smarcel s = xstrdup(exp); 197176349Smarcel old_chain = make_cleanup(xfree, s); 198176489Smarcel if (gdb_parse_exp_1(&s, NULL, 0, &expr) && *s == '\0') { 199176349Smarcel make_cleanup(free_current_contents, &expr); 200176349Smarcel if (gdb_evaluate_expression(expr, &val)) 201176349Smarcel n = value_as_address(val); 202176489Smarcel } 203176349Smarcel do_cleanups(old_chain); 204176349Smarcel gdb_stderr = old_stderr; 205176349Smarcel return (n); 206176489Smarcel} 207176489Smarcel 208176489Smarcel#define MSGBUF_SEQ_TO_POS(size, seq) ((seq) % (size)) 209176349Smarcel 210176489Smarcelvoid 211176349Smarcelkgdb_dmesg(void) 212176349Smarcel{ 213176349Smarcel CORE_ADDR bufp; 214176489Smarcel int size, rseq, wseq; 215176349Smarcel char c; 216176349Smarcel 217176349Smarcel /* 218176489Smarcel * Display the unread portion of the message buffer. This gives the 219176489Smarcel * user a some initial data to work from. 220176349Smarcel */ 221176489Smarcel if (quiet) 222176349Smarcel return; 223176349Smarcel bufp = kgdb_parse("msgbufp->msg_ptr"); 224176349Smarcel size = (int)kgdb_parse("msgbufp->msg_size"); 225176489Smarcel rseq = (int)kgdb_parse("msgbufp->msg_rseq"); 226176349Smarcel wseq = (int)kgdb_parse("msgbufp->msg_wseq"); 227176349Smarcel rseq = MSGBUF_SEQ_TO_POS(size, rseq); 228176349Smarcel wseq = MSGBUF_SEQ_TO_POS(size, wseq); 229176489Smarcel if (bufp == 0 || size == 0 || rseq == wseq) 230176349Smarcel return; 231176349Smarcel 232176349Smarcel printf("\nUnread portion of the kernel message buffer:\n"); 233176349Smarcel while (rseq < wseq) { 234176487Smarcel read_memory(bufp + rseq, &c, 1); 235176349Smarcel putchar(c); 236176349Smarcel rseq++; 237176489Smarcel if (rseq == size) 238176489Smarcel rseq = 0; 239176489Smarcel } 240199534Sraj if (c != '\n') 241176349Smarcel putchar('\n'); 242176489Smarcel putchar('\n'); 243176489Smarcel} 244176489Smarcel 245176349Smarcelstatic void 246176489Smarcelkgdb_init(char *argv0 __unused) 247176489Smarcel{ 248176489Smarcel 249176489Smarcel parse_gdberr = mem_fileopen(); 250199534Sraj set_prompt("(kgdb) "); 251199534Sraj initialize_kgdb_target(); 252176489Smarcel initialize_kld_target(); 253176489Smarcel kgdb_new_objfile_chain = target_new_objfile_hook; 254176489Smarcel target_new_objfile_hook = kgdb_new_objfile; 255176489Smarcel} 256176489Smarcel 257176349Smarcel/* 258176489Smarcel * Remote targets can support any number of syntaxes and we want to 259176489Smarcel * support them all with one addition: we support specifying a device 260176349Smarcel * node for a serial device without the "/dev/" prefix. 261176349Smarcel * 262176349Smarcel * What we do is to stat(2) the existing remote target first. If that 263208538Sraj * fails, we try it with "/dev/" prepended. If that succeeds we use 264176349Smarcel * the resulting path, otherwise we use the original target. If 265176349Smarcel * either stat(2) succeeds make sure the file is either a character 266176349Smarcel * device or a FIFO. 267176349Smarcel */ 268176349Smarcelstatic void 269176349Smarcelverify_remote(void) 270176349Smarcel{ 271176349Smarcel char path[PATH_MAX]; 272176349Smarcel struct stat st; 273208538Sraj 274176489Smarcel if (stat(remote, &st) != 0) { 275176489Smarcel snprintf(path, sizeof(path), "/dev/%s", remote); 276176489Smarcel if (stat(path, &st) != 0) 277176489Smarcel return; 278176489Smarcel free(remote); 279176489Smarcel remote = strdup(path); 280176489Smarcel } 281176489Smarcel if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) 282243693Sgonzo errx(1, "%s: not a special file, FIFO or socket", remote); 283208538Sraj} 284243693Sgonzo 285243693Sgonzostatic void 286176489Smarceladd_arg(struct captured_main_args *args, char *arg) 287176489Smarcel{ 288176489Smarcel 289176349Smarcel args->argc++; 290176489Smarcel args->argv = reallocf(args->argv, (args->argc + 1) * sizeof(char *)); 291176489Smarcel if (args->argv == NULL) 292176489Smarcel err(1, "Out of memory building argument list"); 293176489Smarcel args->argv[args->argc] = arg; 294176489Smarcel} 295208538Sraj 296208538Srajint 297208538Srajmain(int argc, char *argv[]) 298208538Sraj{ 299208538Sraj char path[PATH_MAX]; 300176489Smarcel struct stat st; 301176349Smarcel struct captured_main_args args; 302176489Smarcel char *s; 303176349Smarcel int a, ch; 304176489Smarcel 305176489Smarcel dumpnr = -1; 306176489Smarcel 307176489Smarcel strlcpy(crashdir, "/var/crash", sizeof(crashdir)); 308176489Smarcel s = getenv("KGDB_CRASH_DIR"); 309176489Smarcel if (s != NULL) 310176489Smarcel strlcpy(crashdir, s, sizeof(crashdir)); 311176489Smarcel 312176489Smarcel /* Convert long options into short options. */ 313176489Smarcel for (a = 1; a < argc; a++) { 314176349Smarcel s = argv[a]; 315208538Sraj if (s[0] == '-') { 316176489Smarcel s++; 317176489Smarcel /* Long options take either 1 or 2 dashes. */ 318176489Smarcel if (s[0] == '-') 319176489Smarcel s++; 320176489Smarcel if (strcmp(s, "quiet") == 0) 321208538Sraj argv[a] = "-q"; 322176489Smarcel else if (strcmp(s, "fullname") == 0) 323176349Smarcel argv[a] = "-f"; 324208538Sraj } 325176489Smarcel } 326176489Smarcel 327176349Smarcel quiet = 0; 328208538Sraj memset (&args, 0, sizeof args); 329176489Smarcel args.use_windows = 0; 330176349Smarcel args.interpreter_p = INTERP_CONSOLE; 331243693Sgonzo args.argv = malloc(sizeof(char *)); 332243693Sgonzo args.argv[0] = argv[0]; 333243693Sgonzo 334243693Sgonzo while ((ch = getopt(argc, argv, "ac:d:fn:qr:vw")) != -1) { 335243693Sgonzo switch (ch) { 336243693Sgonzo case 'a': 337243693Sgonzo annotation_level++; 338243693Sgonzo break; 339243693Sgonzo case 'c': /* use given core file. */ 340243693Sgonzo if (vmcore != NULL) { 341176489Smarcel warnx("option %c: can only be specified once", 342176489Smarcel optopt); 343176489Smarcel usage(); 344176489Smarcel /* NOTREACHED */ 345176489Smarcel } 346176489Smarcel vmcore = strdup(optarg); 347176489Smarcel break; 348208538Sraj case 'd': /* lookup dumps in given directory. */ 349208538Sraj strlcpy(crashdir, optarg, sizeof(crashdir)); 350208538Sraj break; 351243693Sgonzo case 'f': 352233230Sraj annotation_level = 1; 353233230Sraj break; 354233230Sraj case 'n': /* use dump with given number. */ 355233230Sraj dumpnr = strtol(optarg, &s, 0); 356208538Sraj if (dumpnr < 0 || *s != '\0') { 357208538Sraj warnx("option %c: invalid kernel dump number", 358176489Smarcel optopt); 359176349Smarcel usage(); 360208538Sraj /* NOTREACHED */ 361176489Smarcel } 362176489Smarcel break; 363176489Smarcel case 'q': 364176349Smarcel quiet = 1; 365208538Sraj add_arg(&args, "-q"); 366176489Smarcel break; 367176489Smarcel case 'r': /* use given device for remote session. */ 368176349Smarcel if (remote != NULL) { 369176489Smarcel warnx("option %c: can only be specified once", 370176489Smarcel optopt); 371176349Smarcel usage(); 372246135Sian /* NOTREACHED */ 373246135Sian } 374246135Sian remote = strdup(optarg); 375246135Sian break; 376246135Sian case 'v': /* increase verbosity. */ 377246135Sian verbose++; 378246135Sian break; 379246135Sian case 'w': /* core file is writeable. */ 380246135Sian add_arg(&args, "--write"); 381176489Smarcel break; 382176489Smarcel case '?': 383208538Sraj default: 384208538Sraj usage(); 385176489Smarcel } 386176349Smarcel } 387208538Sraj 388176349Smarcel if (((vmcore != NULL) ? 1 : 0) + ((dumpnr >= 0) ? 1 : 0) + 389 ((remote != NULL) ? 1 : 0) > 1) { 390 warnx("options -c, -n and -r are mutually exclusive"); 391 usage(); 392 /* NOTREACHED */ 393 } 394 395 if (verbose > 1) 396 warnx("using %s as the crash directory", crashdir); 397 398 if (argc > optind) 399 kernel = strdup(argv[optind++]); 400 401 if (argc > optind && (dumpnr >= 0 || remote != NULL)) { 402 warnx("options -n and -r do not take a core file. Ignored"); 403 optind = argc; 404 } 405 406 if (dumpnr >= 0) { 407 snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr); 408 if (stat(path, &st) == -1) 409 err(1, path); 410 if (!S_ISREG(st.st_mode)) 411 errx(1, "%s: not a regular file", path); 412 vmcore = strdup(path); 413 } else if (remote != NULL) { 414 verify_remote(); 415 } else if (argc > optind) { 416 if (vmcore == NULL) 417 vmcore = strdup(argv[optind++]); 418 if (argc > optind) 419 warnx("multiple core files specified. Ignored"); 420 } else if (vmcore == NULL && kernel == NULL) { 421 vmcore = strdup(_PATH_MEM); 422 kernel = strdup(getbootfile()); 423 } 424 425 if (verbose) { 426 if (vmcore != NULL) 427 warnx("core file: %s", vmcore); 428 if (remote != NULL) 429 warnx("device file: %s", remote); 430 if (kernel != NULL) 431 warnx("kernel image: %s", kernel); 432 } 433 434 /* A remote target requires an explicit kernel argument. */ 435 if (remote != NULL && kernel == NULL) { 436 warnx("remote debugging requires a kernel"); 437 usage(); 438 /* NOTREACHED */ 439 } 440 441 /* If we don't have a kernel image yet, try to find one. */ 442 if (kernel == NULL) { 443 if (dumpnr >= 0) 444 kernel_from_dumpnr(dumpnr); 445 446 if (kernel == NULL) 447 errx(1, "couldn't find a suitable kernel image"); 448 if (verbose) 449 warnx("kernel image: %s", kernel); 450 } 451 add_arg(&args, kernel); 452 453 if (vmcore != NULL) 454 add_arg(&args, vmcore); 455 456 /* The libgdb code uses optind too. Reset it... */ 457 optind = 0; 458 459 /* Terminate argv list. */ 460 add_arg(&args, NULL); 461 462 init_ui_hook = kgdb_init; 463 464 kgdb_sniffer_kluge = kgdb_trgt_trapframe_sniffer; 465 466 return (gdb_main(&args)); 467} 468