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