main.c revision 142151
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 142151 2005-02-20 22:55:07Z kan $"); 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 <inferior.h> 54#include <interps.h> 55#include <cli-out.h> 56#include <main.h> 57#include <target.h> 58#include <top.h> 59#include <bfd.h> 60#include <gdbcore.h> 61 62extern void (*init_ui_hook)(char *); 63 64extern void symbol_file_add_main (char *args, int from_tty); 65 66#include "kgdb.h" 67 68kvm_t *kvm; 69 70static int dumpnr; 71static int verbose; 72 73static char crashdir[PATH_MAX]; 74static char *kernel; 75static char *remote; 76static char *vmcore; 77 78static void (*kgdb_new_objfile_chain)(struct objfile * objfile); 79 80static void 81usage(void) 82{ 83 84 fprintf(stderr, 85 "usage: %s [-a] [-v] [-d crashdir] [-c core | -n dumpnr | -r device]\n" 86 "\t[kernel [core]]\n", getprogname()); 87 exit(1); 88} 89 90static void 91kernel_from_dumpnr(int nr) 92{ 93 char path[PATH_MAX]; 94 FILE *info; 95 char *s; 96 struct stat st; 97 int l; 98 99 /* 100 * If there's a kernel image right here in the crash directory, then 101 * use it. The kernel image is either called kernel.<nr> or is in a 102 * subdirectory kernel.<nr> and called kernel. The latter allows us 103 * to collect the modules in the same place. 104 */ 105 snprintf(path, sizeof(path), "%s/kernel.%d", crashdir, nr); 106 if (stat(path, &st) == 0) { 107 if (S_ISREG(st.st_mode)) { 108 kernel = strdup(path); 109 return; 110 } 111 if (S_ISDIR(st.st_mode)) { 112 snprintf(path, sizeof(path), "%s/kernel.%d/kernel", 113 crashdir, nr); 114 if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { 115 kernel = strdup(path); 116 return; 117 } 118 } 119 } 120 121 /* 122 * No kernel image here. Parse the dump header. The kernel object 123 * directory can be found there and we probably have the kernel 124 * image still in it. The object directory may also have a kernel 125 * with debugging info (called kernel.debug). If we have a debug 126 * kernel, use it. 127 */ 128 snprintf(path, sizeof(path), "%s/info.%d", crashdir, nr); 129 info = fopen(path, "r"); 130 if (info == NULL) { 131 warn(path); 132 return; 133 } 134 while (fgets(path, sizeof(path), info) != NULL) { 135 l = strlen(path); 136 if (l > 0 && path[l - 1] == '\n') 137 path[--l] = '\0'; 138 if (strncmp(path, " ", 4) == 0) { 139 s = strchr(path, ':'); 140 s = (s == NULL) ? path + 4 : s + 1; 141 l = snprintf(path, sizeof(path), "%s/kernel.debug", s); 142 if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { 143 path[l - 6] = '\0'; 144 if (stat(path, &st) == -1 || 145 !S_ISREG(st.st_mode)) 146 break; 147 } 148 kernel = strdup(path); 149 break; 150 } 151 } 152 fclose(info); 153} 154 155static void 156kgdb_new_objfile(struct objfile *objfile) 157{ 158#if 0 159 printf("XXX: %s(%p)\n", __func__, objfile); 160 if (objfile != NULL) { 161 goto out; 162 } 163 164out: 165#endif 166 if (kgdb_new_objfile_chain != NULL) 167 kgdb_new_objfile_chain(objfile); 168} 169 170static void 171kgdb_init_target(void) 172{ 173 bfd *kern_bfd; 174 int kern_desc; 175 176 kern_desc = open(kernel, O_RDONLY); 177 if (kern_desc == -1) 178 errx(1, "couldn't open a kernel image"); 179 180 kern_bfd = bfd_fdopenr(kernel, gnutarget, kern_desc); 181 if (kern_bfd == NULL) { 182 close(kern_desc); 183 errx(1, "\"%s\": can't open to probe ABI: %s.", kernel, 184 bfd_errmsg (bfd_get_error ())); 185 } 186 bfd_set_cacheable(kern_bfd, 1); 187 188 if (!bfd_check_format (kern_bfd, bfd_object)) { 189 bfd_close(kern_bfd); 190 errx(1, "\"%s\": not in executable format: %s", kernel, 191 bfd_errmsg(bfd_get_error())); 192 } 193 194 set_gdbarch_from_file (kern_bfd); 195 bfd_close(kern_bfd); 196 197 symbol_file_add_main (kernel, 0); 198 if (remote) 199 push_remote_target (remote, 0); 200 else 201 kgdb_target(); 202} 203 204static void 205kgdb_interp_command_loop(void *data) 206{ 207 static int once = 0; 208 209 if (!once) { 210 once = 1; 211 kgdb_init_target(); 212 kgdb_target(); 213 print_stack_frame (get_selected_frame (), 214 frame_relative_level (get_selected_frame ()), 1); 215 } 216 command_loop(); 217} 218 219static void 220kgdb_init(char *argv0 __unused) 221{ 222 static struct interp_procs procs = { 223 NULL, 224 NULL, 225 NULL, 226 NULL, 227 NULL, 228 kgdb_interp_command_loop 229 }; 230 struct interp *kgdb; 231 kgdb = interp_new("kgdb", NULL, cli_out_new(gdb_stdout), &procs); 232 interp_add(kgdb); 233 234 set_prompt("(kgdb) "); 235 kgdb_new_objfile_chain = target_new_objfile_hook; 236 target_new_objfile_hook = kgdb_new_objfile; 237} 238 239int 240main(int argc, char *argv[]) 241{ 242 char path[PATH_MAX]; 243 struct stat st; 244 struct captured_main_args args; 245 char *s; 246 int ch; 247 248 dumpnr = -1; 249 250 strlcpy(crashdir, "/var/crash", sizeof(crashdir)); 251 s = getenv("KGDB_CRASH_DIR"); 252 if (s != NULL) 253 strlcpy(crashdir, s, sizeof(crashdir)); 254 255 while ((ch = getopt(argc, argv, "ac:d:n:r:v")) != -1) { 256 switch (ch) { 257 case 'a': 258 annotation_level++; 259 break; 260 case 'c': /* use given core file. */ 261 if (vmcore != NULL) { 262 warnx("option %c: can only be specified once", 263 optopt); 264 usage(); 265 /* NOTREACHED */ 266 } 267 vmcore = strdup(optarg); 268 break; 269 case 'd': /* lookup dumps in given directory. */ 270 strlcpy(crashdir, optarg, sizeof(crashdir)); 271 break; 272 case 'n': /* use dump with given number. */ 273 dumpnr = strtol(optarg, &s, 0); 274 if (dumpnr < 0 || *s != '\0') { 275 warnx("option %c: invalid kernel dump number", 276 optopt); 277 usage(); 278 /* NOTREACHED */ 279 } 280 break; 281 case 'r': /* use given device for remote session. */ 282 if (remote != NULL) { 283 warnx("option %c: can only be specified once", 284 optopt); 285 usage(); 286 /* NOTREACHED */ 287 } 288 remote = strdup(optarg); 289 break; 290 case 'v': /* increase verbosity. */ 291 verbose++; 292 break; 293 case '?': 294 default: 295 usage(); 296 } 297 } 298 299 if (((vmcore != NULL) ? 1 : 0) + ((dumpnr >= 0) ? 1 : 0) + 300 ((remote != NULL) ? 1 : 0) > 1) { 301 warnx("options -c, -n and -r are mutually exclusive"); 302 usage(); 303 /* NOTREACHED */ 304 } 305 306 if (verbose > 1) 307 warnx("using %s as the crash directory", crashdir); 308 309 if (argc > optind) 310 kernel = strdup(argv[optind++]); 311 312 if (argc > optind && (dumpnr >= 0 || remote != NULL)) { 313 warnx("options -n and -r do not take a core file. Ignored"); 314 optind = argc; 315 } 316 317 if (dumpnr >= 0) { 318 snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr); 319 if (stat(path, &st) == -1) 320 err(1, path); 321 if (!S_ISREG(st.st_mode)) 322 errx(1, "%s: not a regular file", path); 323 vmcore = strdup(path); 324 } else if (remote != NULL && remote[0] != ':' && remote[0] != '|') { 325 if (stat(remote, &st) != 0) { 326 snprintf(path, sizeof(path), "/dev/%s", remote); 327 if (stat(path, &st) != 0) { 328 err(1, "%s", remote); 329 /* NOTREACHED */ 330 } 331 free(remote); 332 remote = strdup(path); 333 } 334 if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) { 335 errx(1, "%s: not a special file, FIFO or socket", 336 remote); 337 /* NOTREACHED */ 338 } 339 } else if (argc > optind) { 340 if (vmcore == NULL) 341 vmcore = strdup(argv[optind++]); 342 if (argc > optind) 343 warnx("multiple core files specified. Ignored"); 344 } else if (vmcore == NULL && kernel == NULL) { 345 vmcore = strdup(_PATH_MEM); 346 kernel = strdup(getbootfile()); 347 } 348 349 if (verbose) { 350 if (vmcore != NULL) 351 warnx("core file: %s", vmcore); 352 if (remote != NULL) 353 warnx("device file: %s", remote); 354 if (kernel != NULL) 355 warnx("kernel image: %s", kernel); 356 } 357 358 /* 359 * At this point we must either have a core file or have a kernel 360 * with a remote target. 361 */ 362 if (remote != NULL && kernel == NULL) { 363 warnx("remote debugging requires a kernel"); 364 usage(); 365 /* NOTREACHED */ 366 } 367 if (vmcore == NULL && remote == NULL) { 368 warnx("need a core file or a device for remote debugging"); 369 usage(); 370 /* NOTREACHED */ 371 } 372 373 /* If we don't have a kernel image yet, try to find one. */ 374 if (kernel == NULL) { 375 if (dumpnr >= 0) 376 kernel_from_dumpnr(dumpnr); 377 378 if (kernel == NULL) 379 errx(1, "couldn't find a suitable kernel image"); 380 if (verbose) 381 warnx("kernel image: %s", kernel); 382 } 383 384 if (remote == NULL) { 385 s = malloc(_POSIX2_LINE_MAX); 386 kvm = kvm_openfiles(kernel, vmcore, NULL, O_RDONLY, s); 387 if (kvm == NULL) 388 errx(1, s); 389 free(s); 390 kgdb_thr_init(); 391 } 392 393 memset (&args, 0, sizeof args); 394 args.argc = 1; 395 args.argv = argv; 396 args.use_windows = 0; 397 args.interpreter_p = "kgdb"; 398 399 init_ui_hook = kgdb_init; 400 401 return (gdb_main(&args)); 402} 403