ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/pack/freebsd/gdb6/files/kvm-fbsd.c
Revision: 2
Committed: 2007-01-31T14:59:36-08:00 (18 years, 4 months ago) by douglas
Content type: text/x-c
File size: 12876 byte(s)
Log Message:
This needs fixing...

File Contents

# Content
1 /* Kernel core dump functions below target vector, for GDB.
2 Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include <sys/cdefs.h>
23 __FBSDID("$FreeBSD: ports/devel/gdb6/files/kvm-fbsd.c,v 1.2 2004/06/20 22:22:02 obrien Exp $");
24
25 /*
26 * This works like "remote" but, you use it like this:
27 * target kcore /dev/mem
28 * or
29 * target kcore /var/crash/host/core.0
30 *
31 * This way makes it easy to short-circut the whole bfd monster,
32 * and direct the inferior stuff to our libkvm implementation.
33 *
34 */
35
36 #include <sys/param.h>
37 #include <sys/user.h>
38 #include <machine/frame.h>
39 //#include <sys/proc.h>
40 //#include <sys/sysctl.h>
41 //#include <sys/time.h>
42 //#include <sys/user.h>
43
44 #include <ctype.h>
45 //#include <errno.h>
46 //#include <signal.h>
47 #include <fcntl.h>
48 #include <kvm.h>
49 #include <sys/sysctl.h>
50 #include <paths.h>
51
52 #include "defs.h"
53 #include "gdb_string.h"
54 #include "frame.h" /* required by inferior.h */
55 #include "inferior.h"
56 //#include "symtab.h"
57 #include "symfile.h"
58 #include "objfiles.h"
59 #include "command.h"
60 #include "bfd.h"
61 //#include "target.h"
62 #include "gdbcore.h"
63 #include "solist.h"
64 #include "regcache.h"
65 #include <readline/tilde.h>
66
67 #include "kvm-fbsd.h"
68
69 #if __FreeBSD_version >= 500032
70 static void
71 kcore_files_info (struct target_ops *);
72
73 static void
74 kcore_close (int);
75
76 static void
77 get_kcore_registers (int);
78
79
80 /*
81 static int
82 xfer_mem (CORE_ADDR, char *, int, int, struct mem_attrib *,
83 struct target_ops *);
84 */
85
86 static int
87 xfer_umem (CORE_ADDR, char *, int, int);
88
89 static char *core_file;
90 static kvm_t *core_kd;
91 static struct pcb cur_pcb;
92 static struct kinfo_proc *cur_proc;
93
94 static struct target_ops kcore_ops;
95
96 int kernel_debugging;
97 int kernel_writablecore;
98
99 /* Read the "thing" at kernel address 'addr' into the space pointed to
100 by point. The length of the "thing" is determined by the type of p.
101 Result is non-zero if transfer fails. */
102
103 #define kvread(addr, p) \
104 (target_read_memory ((CORE_ADDR) (addr), (char *) (p), sizeof (*(p))))
105
106 static CORE_ADDR
107 ksym_kernbase (void)
108 {
109 static CORE_ADDR kernbase;
110 struct minimal_symbol *sym;
111
112 if (kernbase == 0)
113 {
114 sym = lookup_minimal_symbol ("kernbase", NULL, NULL);
115 if (sym == NULL) {
116 kernbase = KERNBASE;
117 } else {
118 kernbase = SYMBOL_VALUE_ADDRESS (sym);
119 }
120 }
121 return kernbase;
122 }
123
124 #define KERNOFF (ksym_kernbase ())
125 #define INKERNEL(x) ((x) >= KERNOFF)
126
127 CORE_ADDR
128 ksym_lookup(const char *name)
129 {
130 struct minimal_symbol *sym;
131
132 sym = lookup_minimal_symbol (name, NULL, NULL);
133 if (sym == NULL)
134 error ("kernel symbol `%s' not found.", name);
135
136 return SYMBOL_VALUE_ADDRESS (sym);
137 }
138
139 /* Provide the address of an initial PCB to use.
140 If this is a crash dump, try for "dumppcb".
141 If no "dumppcb" or it's /dev/mem, use proc0.
142 Return the core address of the PCB we found. */
143
144 static CORE_ADDR
145 initial_pcb (void)
146 {
147 struct minimal_symbol *sym;
148 CORE_ADDR addr;
149 void *val;
150
151 /* Make sure things are open... */
152 if (!core_kd || !core_file)
153 return (0);
154
155 /* If this is NOT /dev/mem try for dumppcb. */
156 if (strncmp (core_file, _PATH_DEV, sizeof _PATH_DEV - 1))
157 {
158 sym = lookup_minimal_symbol ("dumppcb", NULL, NULL);
159 if (sym != NULL)
160 {
161 addr = SYMBOL_VALUE_ADDRESS (sym);
162 return (addr);
163 }
164 }
165
166 /* OK, just use thread0's pcb. Note that curproc might
167 not exist, and if it does, it will point to gdb.
168 Therefore, just use proc0 and let the user set
169 some other context if they care about it. */
170
171 addr = ksym_lookup ("thread0");
172 if (kvread (addr, &val))
173 {
174 error ("cannot read thread0 pointer at %lx\n", addr);
175 val = 0;
176 }
177 else
178 {
179 /* Read the PCB address in thread structure. */
180 addr += offsetof (struct thread, td_pcb);
181 if (kvread (addr, &val))
182 {
183 error ("cannot read thread0->td_pcb pointer at %lx\n", addr);
184 val = 0;
185 }
186 }
187
188 /* thread0 is wholly in the kernel and cur_proc is only used for
189 reading user mem, so no point in setting this up. */
190 cur_proc = 0;
191
192 return ((CORE_ADDR)val);
193 }
194
195 /* Set the current context to that of the PCB struct at the system address
196 passed. */
197
198 static int
199 set_context (CORE_ADDR addr)
200 {
201 CORE_ADDR procaddr = 0;
202
203 if (kvread (addr, &cur_pcb))
204 error ("cannot read pcb at %#lx", addr);
205
206 /* Fetch all registers from core file. */
207 target_fetch_registers (-1);
208
209 /* Now, set up the frame cache, and print the top of stack. */
210 flush_cached_frames ();
211 /*DEO XXX
212 set_current_frame (create_new_frame (read_fp (), read_pc ()));
213 set_current_frame (create_new_frame (deprecated_read_fp (), read_pc ()));
214 select_frame (get_current_frame ());
215 */
216 print_stack_frame (get_selected_frame (), -1, 1);
217 return (0);
218 }
219
220 /* Discard all vestiges of any previous core file and mark data and stack
221 spaces as empty. */
222
223 /* ARGSUSED */
224 static void
225 kcore_close (int quitting)
226 {
227
228 inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */
229
230 if (core_kd)
231 {
232 kvm_close (core_kd);
233 free (core_file);
234 core_file = NULL;
235 core_kd = NULL;
236 }
237 }
238
239 /* This routine opens and sets up the core file bfd. */
240
241 static void
242 kcore_open (char *filename /* the core file */, int from_tty)
243 {
244 kvm_t *kd;
245 const char *p;
246 struct cleanup *old_chain;
247 char buf[256], *cp;
248 int ontop;
249 CORE_ADDR addr;
250
251 target_preopen (from_tty);
252
253 /* The exec file is required for symbols. */
254 if (exec_bfd == NULL)
255 error ("No kernel exec file specified");
256
257 if (core_kd)
258 {
259 error ("No core file specified."
260 " (Use `detach' to stop debugging a core file.)");
261 return;
262 }
263
264 if (!filename)
265 {
266 error ("No core file specified.");
267 return;
268 }
269
270 filename = tilde_expand (filename);
271 if (filename[0] != '/')
272 {
273 cp = concat (current_directory, "/", filename, NULL);
274 free (filename);
275 filename = cp;
276 }
277
278 old_chain = make_cleanup (free, filename);
279
280 kd = kvm_open (bfd_get_filename(exec_bfd), filename, NULL,
281 kernel_writablecore ? O_RDWR: O_RDONLY, 0);
282 if (kd == NULL)
283 {
284 perror_with_name (filename);
285 return;
286 }
287
288 /* Looks semi-reasonable. Toss the old core file and work on the new. */
289
290 discard_cleanups (old_chain); /* Don't free filename any more. */
291 core_file = filename;
292 unpush_target (&kcore_ops);
293 ontop = !push_target (&kcore_ops);
294
295 /* Note unpush_target (above) calls kcore_close. */
296 core_kd = kd;
297
298 /* Print out the panic string if there is one. */
299 if (kvread (ksym_lookup ("panicstr"), &addr) == 0 &&
300 addr != 0 &&
301 target_read_memory (addr, buf, sizeof(buf)) == 0)
302 {
303
304 for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
305 if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp)))
306 *cp = '?';
307 *cp = '\0';
308 if (buf[0] != '\0')
309 printf_filtered ("panic: %s\n", buf);
310 }
311
312 /* Print all the panic messages if possible. */
313 if (symfile_objfile != NULL)
314 {
315 printf ("panic messages:\n---\n");
316 snprintf (buf, sizeof buf,
317 "/sbin/dmesg -N %s -M %s | \
318 /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \
319 { if (printing) print $0 }'",
320 symfile_objfile->name, filename);
321 fflush (stdout);
322 system (buf);
323 printf ("---\n");
324 }
325
326 if (!ontop)
327 {
328 warning ("you won't be able to access this core file until you terminate\n"
329 "your %s; do ``info files''", target_longname);
330 return;
331 }
332
333 /* Now, set up process context, and print the top of stack. */
334 (void)set_context (initial_pcb());
335 print_stack_frame (get_selected_frame (),
336 frame_relative_level (get_selected_frame ()), 1);
337 }
338
339 static void
340 kcore_detach (char *args, int from_tty)
341 {
342 if (args)
343 error ("Too many arguments");
344 unpush_target (&kcore_ops);
345 reinit_frame_cache ();
346 if (from_tty)
347 printf_filtered ("No kernel core file now.\n");
348 }
349
350 /* Get the registers out of a core file. This is the machine-
351 independent part. Fetch_core_registers is the machine-dependent
352 part, typically implemented in the xm-file for each architecture. */
353
354 /* We just get all the registers, so we don't use regno. */
355
356 /* ARGSUSED */
357 static void
358 get_kcore_registers (int regno)
359 {
360
361 /* XXX - Only read the pcb when set_context() is called.
362 When looking at a live kernel this may be a problem,
363 but the user can do another "proc" or "pcb" command to
364 grab a new copy of the pcb... */
365
366 /* Zero out register set then fill in the ones we know about. */
367 fetch_kcore_registers (&cur_pcb);
368 }
369
370 static void
371 kcore_files_info (t)
372 struct target_ops *t;
373 {
374 printf_filtered ("\t`%s'\n", core_file);
375 }
376
377 /* If mourn is being called in all the right places, this could be say
378 `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */
379
380 /*
381 static int
382 ignore (CORE_ADDR addr, char *contents)
383 {
384 return 0;
385 }
386 */
387
388 static int
389 xfer_kmem (CORE_ADDR memaddr, char *myaddr, int len, int write,
390 struct mem_attrib *attrib, struct target_ops *target)
391 {
392 int n;
393
394
395 if (!INKERNEL (memaddr))
396 return xfer_umem (memaddr, myaddr, len, write);
397
398 if (core_kd == NULL)
399 return 0;
400
401 if (write)
402 n = kvm_write (core_kd, memaddr, myaddr, len);
403 else
404 n = kvm_read (core_kd, memaddr, myaddr, len) ;
405 if (n < 0) {
406 fprintf_unfiltered (gdb_stderr, "can not access 0x%lx, %s\n",
407 memaddr, kvm_geterr (core_kd));
408 n = 0;
409 }
410
411 return n;
412 }
413
414
415 static int
416 xfer_umem (CORE_ADDR memaddr, char *myaddr, int len, int write /* ignored */)
417 {
418 int n = 0;
419
420 if (cur_proc == 0)
421 {
422 error ("---Can't read userspace from dump, or kernel process---\n");
423 return 0;
424 }
425
426 if (write)
427 error ("kvm_uwrite unimplemented\n");
428 else
429 n = kvm_uread (core_kd, cur_proc, memaddr, myaddr, len) ;
430
431 if (n < 0)
432 return 0;
433
434 return n;
435 }
436
437 static void
438 set_proc_cmd (char *arg, int from_tty)
439 {
440 CORE_ADDR addr, pid_addr, first_td;
441 void *val;
442 struct kinfo_proc *kp;
443 int cnt;
444 pid_t pid;
445
446 if (!arg)
447 error_no_arg ("proc address for the new context");
448
449 if (core_kd == NULL)
450 error ("no kernel core file");
451
452 addr = (CORE_ADDR) parse_and_eval_address (arg);
453
454 if (!INKERNEL (addr))
455 {
456 kp = kvm_getprocs (core_kd, KERN_PROC_PID, addr, &cnt);
457 if (!cnt)
458 error ("invalid pid");
459 addr = (CORE_ADDR)kp->ki_paddr;
460 cur_proc = kp;
461 }
462 else
463 {
464 /* Update cur_proc. */
465 pid_addr = addr + offsetof (struct proc, p_pid);
466 if (kvread (pid_addr, &pid))
467 error ("cannot read pid ptr");
468 cur_proc = kvm_getprocs (core_kd, KERN_PROC_PID, pid, &cnt);
469 if (!cnt)
470 error("invalid pid");
471 }
472
473 /* Find the first thread in the process. XXXKSE */
474 addr += offsetof (struct proc, p_threads.tqh_first);
475 if (kvread (addr, &first_td))
476 error ("cannot read thread ptr");
477
478 /* Read the PCB address in thread structure. */
479 addr = first_td + offsetof (struct thread, td_pcb);
480 if (kvread (addr, &val))
481 error("cannot read pcb ptr");
482
483 /* Read the PCB address in proc structure. */
484 if (set_context ((CORE_ADDR) val))
485 error ("invalid proc address");
486 }
487 #else
488 int kernel_debugging = 0;
489 int kernel_writablecore = 0;
490
491 CORE_ADDR
492 fbsd_kern_frame_saved_pc (struct frame_info *fi)
493 {
494 return 0;
495 }
496 #endif
497
498 void
499 _initialize_kcorelow (void)
500 {
501 #if __FreeBSD_version >= 500032
502 kcore_ops.to_shortname = "kcore";
503 kcore_ops.to_longname = "Kernel core dump file";
504 kcore_ops.to_doc =
505 "Use a core file as a target. Specify the filename of the core file.";
506 kcore_ops.to_open = kcore_open;
507 kcore_ops.to_close = kcore_close;
508 kcore_ops.to_attach = find_default_attach;
509 kcore_ops.to_detach = kcore_detach;
510 kcore_ops.to_fetch_registers = get_kcore_registers;
511 kcore_ops.to_xfer_memory = xfer_kmem;
512 kcore_ops.to_files_info = kcore_files_info;
513 kcore_ops.to_create_inferior = find_default_create_inferior;
514 kcore_ops.to_stratum = kcore_stratum;
515 kcore_ops.to_has_memory = 1;
516 kcore_ops.to_has_stack = 1;
517 kcore_ops.to_has_registers = 1;
518 kcore_ops.to_magic = OPS_MAGIC;
519
520 add_target (&kcore_ops);
521 add_com ("proc", class_obscure, set_proc_cmd, "Set current process context");
522 #endif
523 }