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