1132624Smarcel/* 2132624Smarcel * Copyright (c) 2004 Marcel Moolenaar 3132624Smarcel * All rights reserved. 4132624Smarcel * 5132624Smarcel * Redistribution and use in source and binary forms, with or without 6132624Smarcel * modification, are permitted provided that the following conditions 7132624Smarcel * are met: 8132624Smarcel * 9132624Smarcel * 1. Redistributions of source code must retain the above copyright 10132624Smarcel * notice, this list of conditions and the following disclaimer. 11132624Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12132624Smarcel * notice, this list of conditions and the following disclaimer in the 13132624Smarcel * documentation and/or other materials provided with the distribution. 14132624Smarcel * 15132624Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16132624Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17132624Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18132624Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19132624Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20132624Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21132624Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22132624Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23132624Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24132624Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25132624Smarcel */ 26132624Smarcel 27132624Smarcel#include <sys/cdefs.h> 28132624Smarcel__FBSDID("$FreeBSD$"); 29132624Smarcel 30132624Smarcel#include <sys/param.h> 31132624Smarcel#include <sys/stat.h> 32132624Smarcel#include <sys/types.h> 33132624Smarcel#include <sys/ioctl.h> 34132624Smarcel#include <sys/resource.h> 35132624Smarcel#include <sys/select.h> 36132624Smarcel#include <sys/time.h> 37132624Smarcel#include <sys/wait.h> 38132624Smarcel#include <errno.h> 39132624Smarcel#include <err.h> 40132624Smarcel#include <inttypes.h> 41132624Smarcel#include <kvm.h> 42132624Smarcel#include <limits.h> 43133739Smarcel#include <paths.h> 44132624Smarcel#include <stdio.h> 45132624Smarcel#include <stdlib.h> 46132624Smarcel#include <string.h> 47132624Smarcel#include <unistd.h> 48132624Smarcel 49132624Smarcel/* libgdb stuff. */ 50132624Smarcel#include <defs.h> 51132624Smarcel#include <frame.h> 52149954Smarcel#include <frame-unwind.h> 53132624Smarcel#include <inferior.h> 54132624Smarcel#include <interps.h> 55132624Smarcel#include <cli-out.h> 56132624Smarcel#include <main.h> 57178670Sjhb#include <objfiles.h> 58132624Smarcel#include <target.h> 59132624Smarcel#include <top.h> 60178670Sjhb#include <ui-file.h> 61142151Skan#include <bfd.h> 62142151Skan#include <gdbcore.h> 63177715Sjhb#include <wrapper.h> 64132624Smarcel 65149954Smarcelextern frame_unwind_sniffer_ftype *kgdb_sniffer_kluge; 66149954Smarcel 67132624Smarcel#include "kgdb.h" 68132624Smarcel 69132624Smarcelstatic int dumpnr; 70175770Sjhbstatic int quiet; 71132624Smarcelstatic int verbose; 72132624Smarcel 73132624Smarcelstatic char crashdir[PATH_MAX]; 74178670Sjhbstatic char *kernel; 75133739Smarcelstatic char *remote; 76132624Smarcelstatic char *vmcore; 77178670Sjhbstatic struct ui_file *parse_gdberr; 78132624Smarcel 79132624Smarcelstatic void (*kgdb_new_objfile_chain)(struct objfile * objfile); 80132624Smarcel 81132624Smarcelstatic void 82132624Smarcelusage(void) 83132624Smarcel{ 84133739Smarcel 85132624Smarcel fprintf(stderr, 86238283Srwatson "usage: %s [-afqvw] [-d crashdir] [-c core | -n dumpnr | -r device]\n" 87133739Smarcel "\t[kernel [core]]\n", getprogname()); 88132624Smarcel exit(1); 89132624Smarcel} 90132624Smarcel 91132624Smarcelstatic void 92133739Smarcelkernel_from_dumpnr(int nr) 93132624Smarcel{ 94132624Smarcel char path[PATH_MAX]; 95132624Smarcel FILE *info; 96132624Smarcel char *s; 97132624Smarcel struct stat st; 98132624Smarcel int l; 99132624Smarcel 100132624Smarcel /* 101133739Smarcel * If there's a kernel image right here in the crash directory, then 102133739Smarcel * use it. The kernel image is either called kernel.<nr> or is in a 103133739Smarcel * subdirectory kernel.<nr> and called kernel. The latter allows us 104133739Smarcel * to collect the modules in the same place. 105132624Smarcel */ 106132624Smarcel snprintf(path, sizeof(path), "%s/kernel.%d", crashdir, nr); 107132624Smarcel if (stat(path, &st) == 0) { 108132624Smarcel if (S_ISREG(st.st_mode)) { 109132624Smarcel kernel = strdup(path); 110132624Smarcel return; 111132624Smarcel } 112132624Smarcel if (S_ISDIR(st.st_mode)) { 113132624Smarcel snprintf(path, sizeof(path), "%s/kernel.%d/kernel", 114132624Smarcel crashdir, nr); 115132624Smarcel if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { 116132624Smarcel kernel = strdup(path); 117132624Smarcel return; 118132624Smarcel } 119132624Smarcel } 120132624Smarcel } 121132624Smarcel 122132624Smarcel /* 123133739Smarcel * No kernel image here. Parse the dump header. The kernel object 124132624Smarcel * directory can be found there and we probably have the kernel 125133739Smarcel * image still in it. The object directory may also have a kernel 126133739Smarcel * with debugging info (called kernel.debug). If we have a debug 127133739Smarcel * kernel, use it. 128132624Smarcel */ 129132624Smarcel snprintf(path, sizeof(path), "%s/info.%d", crashdir, nr); 130132624Smarcel info = fopen(path, "r"); 131132624Smarcel if (info == NULL) { 132217749Semaste warn("%s", path); 133132624Smarcel return; 134132624Smarcel } 135132624Smarcel while (fgets(path, sizeof(path), info) != NULL) { 136132624Smarcel l = strlen(path); 137132624Smarcel if (l > 0 && path[l - 1] == '\n') 138132624Smarcel path[--l] = '\0'; 139132624Smarcel if (strncmp(path, " ", 4) == 0) { 140132624Smarcel s = strchr(path, ':'); 141132624Smarcel s = (s == NULL) ? path + 4 : s + 1; 142132624Smarcel l = snprintf(path, sizeof(path), "%s/kernel.debug", s); 143132624Smarcel if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { 144132624Smarcel path[l - 6] = '\0'; 145132624Smarcel if (stat(path, &st) == -1 || 146132624Smarcel !S_ISREG(st.st_mode)) 147132624Smarcel break; 148132624Smarcel } 149132624Smarcel kernel = strdup(path); 150132624Smarcel break; 151132624Smarcel } 152132624Smarcel } 153132624Smarcel fclose(info); 154132624Smarcel} 155132624Smarcel 156132624Smarcelstatic void 157132624Smarcelkgdb_new_objfile(struct objfile *objfile) 158132624Smarcel{ 159178670Sjhb static int once = 1; 160132624Smarcel 161178670Sjhb kld_new_objfile(objfile); 162178670Sjhb kgdb_trgt_new_objfile(objfile); 163178670Sjhb 164132624Smarcel if (kgdb_new_objfile_chain != NULL) 165132624Smarcel kgdb_new_objfile_chain(objfile); 166178670Sjhb 167178670Sjhb if (once && objfile != NULL && objfile == symfile_objfile) { 168178670Sjhb /* 169178670Sjhb * The initial kernel has just been loaded. Start the 170178670Sjhb * remote target if we have one. 171178670Sjhb */ 172178670Sjhb once = 0; 173178670Sjhb if (remote != NULL) 174178670Sjhb push_remote_target (remote, 0); 175178670Sjhb } 176132624Smarcel} 177132624Smarcel 178178670Sjhb/* 179178670Sjhb * Parse an expression and return its value. If 'quiet' is true, then 180178670Sjhb * any error messages from the parser are masked. 181178670Sjhb */ 182175416SjhbCORE_ADDR 183178670Sjhbkgdb_parse_1(const char *exp, int quiet) 184148801Smarcel{ 185178670Sjhb struct ui_file *old_stderr; 186148801Smarcel struct cleanup *old_chain; 187148801Smarcel struct expression *expr; 188148801Smarcel struct value *val; 189148801Smarcel char *s; 190148801Smarcel CORE_ADDR n; 191148801Smarcel 192178670Sjhb old_stderr = gdb_stderr; 193178670Sjhb if (quiet) 194178670Sjhb gdb_stderr = parse_gdberr; 195177715Sjhb n = 0; 196177715Sjhb s = xstrdup(exp); 197177715Sjhb old_chain = make_cleanup(xfree, s); 198177715Sjhb if (gdb_parse_exp_1(&s, NULL, 0, &expr) && *s == '\0') { 199177715Sjhb make_cleanup(free_current_contents, &expr); 200177715Sjhb if (gdb_evaluate_expression(expr, &val)) 201177715Sjhb n = value_as_address(val); 202177715Sjhb } 203148801Smarcel do_cleanups(old_chain); 204178670Sjhb gdb_stderr = old_stderr; 205148801Smarcel return (n); 206148801Smarcel} 207148801Smarcel 208151683Smarcel#define MSGBUF_SEQ_TO_POS(size, seq) ((seq) % (size)) 209151683Smarcel 210178670Sjhbvoid 211178670Sjhbkgdb_dmesg(void) 212142151Skan{ 213148801Smarcel CORE_ADDR bufp; 214148801Smarcel int size, rseq, wseq; 215148801Smarcel char c; 216142151Skan 217148801Smarcel /* 218148801Smarcel * Display the unread portion of the message buffer. This gives the 219148801Smarcel * user a some initial data to work from. 220148801Smarcel */ 221175770Sjhb if (quiet) 222175770Sjhb return; 223148801Smarcel bufp = kgdb_parse("msgbufp->msg_ptr"); 224148801Smarcel size = (int)kgdb_parse("msgbufp->msg_size"); 225213013Semaste if (bufp == 0 || size == 0) 226213013Semaste return; 227148801Smarcel rseq = (int)kgdb_parse("msgbufp->msg_rseq"); 228148801Smarcel wseq = (int)kgdb_parse("msgbufp->msg_wseq"); 229151683Smarcel rseq = MSGBUF_SEQ_TO_POS(size, rseq); 230151683Smarcel wseq = MSGBUF_SEQ_TO_POS(size, wseq); 231213013Semaste if (rseq == wseq) 232148801Smarcel return; 233148801Smarcel 234148801Smarcel printf("\nUnread portion of the kernel message buffer:\n"); 235148801Smarcel while (rseq < wseq) { 236148801Smarcel read_memory(bufp + rseq, &c, 1); 237148801Smarcel putchar(c); 238148801Smarcel rseq++; 239148801Smarcel if (rseq == size) 240148801Smarcel rseq = 0; 241148801Smarcel } 242148801Smarcel if (c != '\n') 243148801Smarcel putchar('\n'); 244148801Smarcel putchar('\n'); 245142151Skan} 246142151Skan 247142151Skanstatic void 248178670Sjhbkgdb_init(char *argv0 __unused) 249132624Smarcel{ 250132624Smarcel 251178670Sjhb parse_gdberr = mem_fileopen(); 252178670Sjhb set_prompt("(kgdb) "); 253178670Sjhb initialize_kgdb_target(); 254178670Sjhb initialize_kld_target(); 255178670Sjhb kgdb_new_objfile_chain = target_new_objfile_hook; 256178670Sjhb target_new_objfile_hook = kgdb_new_objfile; 257178670Sjhb} 258178670Sjhb 259178670Sjhb/* 260178670Sjhb * Remote targets can support any number of syntaxes and we want to 261178670Sjhb * support them all with one addition: we support specifying a device 262178670Sjhb * node for a serial device without the "/dev/" prefix. 263178670Sjhb * 264178670Sjhb * What we do is to stat(2) the existing remote target first. If that 265178670Sjhb * fails, we try it with "/dev/" prepended. If that succeeds we use 266178670Sjhb * the resulting path, otherwise we use the original target. If 267178670Sjhb * either stat(2) succeeds make sure the file is either a character 268178670Sjhb * device or a FIFO. 269178670Sjhb */ 270178670Sjhbstatic void 271178670Sjhbverify_remote(void) 272178670Sjhb{ 273178670Sjhb char path[PATH_MAX]; 274178670Sjhb struct stat st; 275178670Sjhb 276178670Sjhb if (stat(remote, &st) != 0) { 277178670Sjhb snprintf(path, sizeof(path), "/dev/%s", remote); 278178670Sjhb if (stat(path, &st) != 0) 279178670Sjhb return; 280178670Sjhb free(remote); 281178670Sjhb remote = strdup(path); 282132624Smarcel } 283178670Sjhb if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) 284178670Sjhb errx(1, "%s: not a special file, FIFO or socket", remote); 285132624Smarcel} 286132624Smarcel 287132624Smarcelstatic void 288178670Sjhbadd_arg(struct captured_main_args *args, char *arg) 289132624Smarcel{ 290132624Smarcel 291178670Sjhb args->argc++; 292178670Sjhb args->argv = reallocf(args->argv, (args->argc + 1) * sizeof(char *)); 293178670Sjhb if (args->argv == NULL) 294178670Sjhb err(1, "Out of memory building argument list"); 295178670Sjhb args->argv[args->argc] = arg; 296132624Smarcel} 297132624Smarcel 298132624Smarcelint 299132624Smarcelmain(int argc, char *argv[]) 300132624Smarcel{ 301133739Smarcel char path[PATH_MAX]; 302133739Smarcel struct stat st; 303132624Smarcel struct captured_main_args args; 304132624Smarcel char *s; 305178670Sjhb int a, ch; 306132624Smarcel 307132624Smarcel dumpnr = -1; 308132624Smarcel 309132624Smarcel strlcpy(crashdir, "/var/crash", sizeof(crashdir)); 310132624Smarcel s = getenv("KGDB_CRASH_DIR"); 311132624Smarcel if (s != NULL) 312132624Smarcel strlcpy(crashdir, s, sizeof(crashdir)); 313132624Smarcel 314143046Smarcel /* Convert long options into short options. */ 315143046Smarcel for (a = 1; a < argc; a++) { 316143046Smarcel s = argv[a]; 317143046Smarcel if (s[0] == '-') { 318143046Smarcel s++; 319143046Smarcel /* Long options take either 1 or 2 dashes. */ 320143046Smarcel if (s[0] == '-') 321143046Smarcel s++; 322143046Smarcel if (strcmp(s, "quiet") == 0) 323143046Smarcel argv[a] = "-q"; 324143046Smarcel else if (strcmp(s, "fullname") == 0) 325143046Smarcel argv[a] = "-f"; 326143046Smarcel } 327143046Smarcel } 328143046Smarcel 329143046Smarcel quiet = 0; 330178670Sjhb memset (&args, 0, sizeof args); 331178670Sjhb args.use_windows = 0; 332178670Sjhb args.interpreter_p = INTERP_CONSOLE; 333178670Sjhb args.argv = malloc(sizeof(char *)); 334178670Sjhb args.argv[0] = argv[0]; 335143046Smarcel 336154043Skan while ((ch = getopt(argc, argv, "ac:d:fn:qr:vw")) != -1) { 337132624Smarcel switch (ch) { 338137993Sjoerg case 'a': 339137993Sjoerg annotation_level++; 340137993Sjoerg break; 341133739Smarcel case 'c': /* use given core file. */ 342133739Smarcel if (vmcore != NULL) { 343133739Smarcel warnx("option %c: can only be specified once", 344133739Smarcel optopt); 345133739Smarcel usage(); 346133739Smarcel /* NOTREACHED */ 347133739Smarcel } 348133739Smarcel vmcore = strdup(optarg); 349133739Smarcel break; 350133739Smarcel case 'd': /* lookup dumps in given directory. */ 351132624Smarcel strlcpy(crashdir, optarg, sizeof(crashdir)); 352132624Smarcel break; 353143046Smarcel case 'f': 354143046Smarcel annotation_level = 1; 355143046Smarcel break; 356133739Smarcel case 'n': /* use dump with given number. */ 357132624Smarcel dumpnr = strtol(optarg, &s, 0); 358132624Smarcel if (dumpnr < 0 || *s != '\0') { 359132624Smarcel warnx("option %c: invalid kernel dump number", 360132624Smarcel optopt); 361132624Smarcel usage(); 362132624Smarcel /* NOTREACHED */ 363132624Smarcel } 364132624Smarcel break; 365143046Smarcel case 'q': 366143046Smarcel quiet = 1; 367178670Sjhb add_arg(&args, "-q"); 368143046Smarcel break; 369133739Smarcel case 'r': /* use given device for remote session. */ 370133739Smarcel if (remote != NULL) { 371133739Smarcel warnx("option %c: can only be specified once", 372133739Smarcel optopt); 373133739Smarcel usage(); 374133739Smarcel /* NOTREACHED */ 375133739Smarcel } 376133739Smarcel remote = strdup(optarg); 377133739Smarcel break; 378133739Smarcel case 'v': /* increase verbosity. */ 379132624Smarcel verbose++; 380132624Smarcel break; 381154043Skan case 'w': /* core file is writeable. */ 382178670Sjhb add_arg(&args, "--write"); 383154043Skan break; 384132624Smarcel case '?': 385132624Smarcel default: 386132624Smarcel usage(); 387132624Smarcel } 388132624Smarcel } 389132624Smarcel 390133739Smarcel if (((vmcore != NULL) ? 1 : 0) + ((dumpnr >= 0) ? 1 : 0) + 391133739Smarcel ((remote != NULL) ? 1 : 0) > 1) { 392133739Smarcel warnx("options -c, -n and -r are mutually exclusive"); 393133739Smarcel usage(); 394133739Smarcel /* NOTREACHED */ 395133739Smarcel } 396133739Smarcel 397132624Smarcel if (verbose > 1) 398132624Smarcel warnx("using %s as the crash directory", crashdir); 399132624Smarcel 400133739Smarcel if (argc > optind) 401133739Smarcel kernel = strdup(argv[optind++]); 402132624Smarcel 403133739Smarcel if (argc > optind && (dumpnr >= 0 || remote != NULL)) { 404133739Smarcel warnx("options -n and -r do not take a core file. Ignored"); 405133739Smarcel optind = argc; 406132624Smarcel } 407133739Smarcel 408133739Smarcel if (dumpnr >= 0) { 409133739Smarcel snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr); 410133739Smarcel if (stat(path, &st) == -1) 411217749Semaste err(1, "%s", path); 412133739Smarcel if (!S_ISREG(st.st_mode)) 413133739Smarcel errx(1, "%s: not a regular file", path); 414133739Smarcel vmcore = strdup(path); 415178670Sjhb } else if (remote != NULL) { 416178670Sjhb verify_remote(); 417133739Smarcel } else if (argc > optind) { 418133739Smarcel if (vmcore == NULL) 419133739Smarcel vmcore = strdup(argv[optind++]); 420133739Smarcel if (argc > optind) 421133739Smarcel warnx("multiple core files specified. Ignored"); 422133739Smarcel } else if (vmcore == NULL && kernel == NULL) { 423133739Smarcel vmcore = strdup(_PATH_MEM); 424133739Smarcel kernel = strdup(getbootfile()); 425133739Smarcel } 426133739Smarcel 427133739Smarcel if (verbose) { 428132624Smarcel if (vmcore != NULL) 429133739Smarcel warnx("core file: %s", vmcore); 430133739Smarcel if (remote != NULL) 431133739Smarcel warnx("device file: %s", remote); 432133739Smarcel if (kernel != NULL) 433133739Smarcel warnx("kernel image: %s", kernel); 434132624Smarcel } 435132624Smarcel 436178670Sjhb /* A remote target requires an explicit kernel argument. */ 437133739Smarcel if (remote != NULL && kernel == NULL) { 438133739Smarcel warnx("remote debugging requires a kernel"); 439133739Smarcel usage(); 440133739Smarcel /* NOTREACHED */ 441133739Smarcel } 442132624Smarcel 443133739Smarcel /* If we don't have a kernel image yet, try to find one. */ 444133739Smarcel if (kernel == NULL) { 445133739Smarcel if (dumpnr >= 0) 446133739Smarcel kernel_from_dumpnr(dumpnr); 447133739Smarcel 448133739Smarcel if (kernel == NULL) 449133739Smarcel errx(1, "couldn't find a suitable kernel image"); 450133739Smarcel if (verbose) 451133739Smarcel warnx("kernel image: %s", kernel); 452132624Smarcel } 453178670Sjhb add_arg(&args, kernel); 454132624Smarcel 455178670Sjhb if (vmcore != NULL) 456178670Sjhb add_arg(&args, vmcore); 457132624Smarcel 458143046Smarcel /* The libgdb code uses optind too. Reset it... */ 459143046Smarcel optind = 0; 460143046Smarcel 461178670Sjhb /* Terminate argv list. */ 462178670Sjhb add_arg(&args, NULL); 463132624Smarcel 464132624Smarcel init_ui_hook = kgdb_init; 465132624Smarcel 466149954Smarcel kgdb_sniffer_kluge = kgdb_trgt_trapframe_sniffer; 467149954Smarcel 468132624Smarcel return (gdb_main(&args)); 469132624Smarcel} 470