*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / bsd-kvm.c
CommitLineData
2e0c3539
MK
1/* BSD Kernel Data Access Library (libkvm) interface.
2
0fb0cc75 3 Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
2e0c3539
MK
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
2e0c3539
MK
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
2e0c3539
MK
19
20#include "defs.h"
963c4174
MK
21#include "cli/cli-cmds.h"
22#include "command.h"
2e0c3539
MK
23#include "frame.h"
24#include "regcache.h"
25#include "target.h"
963c4174 26#include "value.h"
7f245d65 27#include "gdbcore.h" /* for get_exec_file */
6c613132 28#include "gdbthread.h"
2e0c3539
MK
29
30#include "gdb_assert.h"
31#include <fcntl.h>
32#include <kvm.h>
ac5754fa 33#ifdef HAVE_NLIST_H
2e0c3539 34#include <nlist.h>
ac5754fa 35#endif
2e5a5020 36#include <paths.h>
2e0c3539
MK
37#include "readline/readline.h"
38#include <sys/param.h>
963c4174 39#include <sys/proc.h>
2e0c3539
MK
40#include <sys/user.h>
41
42#include "bsd-kvm.h"
43
2e5a5020
MK
44/* Kernel memory device file. */
45static const char *bsd_kvm_corefile;
46
2e0c3539 47/* Kernel memory interface descriptor. */
2e5a5020 48static kvm_t *core_kd;
2e0c3539
MK
49
50/* Address of process control block. */
2e5a5020 51static struct pcb *bsd_kvm_paddr;
2e0c3539
MK
52
53/* Pointer to architecture-specific function that reconstructs the
54 register state from PCB and supplies it to REGCACHE. */
2e5a5020 55static int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb);
2e0c3539
MK
56
57/* Target ops for libkvm interface. */
2e5a5020 58static struct target_ops bsd_kvm_ops;
2e0c3539 59
6c613132
PA
60/* This is the ptid we use while we're connected to kvm. The kvm
61 target currently doesn't export any view of the running processes,
62 so this represents the kernel task. */
63static ptid_t bsd_kvm_ptid;
64
2e0c3539
MK
65static void
66bsd_kvm_open (char *filename, int from_tty)
67{
68 char errbuf[_POSIX2_LINE_MAX];
69 char *execfile = NULL;
70 kvm_t *temp_kd;
71
72 target_preopen (from_tty);
73
74 if (filename)
75 {
76 char *temp;
77
78 filename = tilde_expand (filename);
79 if (filename[0] != '/')
80 {
1754f103 81 temp = concat (current_directory, "/", filename, (char *)NULL);
2e0c3539
MK
82 xfree (filename);
83 filename = temp;
84 }
85 }
86
7f245d65 87 execfile = get_exec_file (0);
4a35b02a
NW
88 temp_kd = kvm_openfiles (execfile, filename, NULL,
89 write_files ? O_RDWR : O_RDONLY, errbuf);
2e0c3539 90 if (temp_kd == NULL)
8a3fe4f8 91 error (("%s"), errbuf);
2e0c3539 92
2e5a5020 93 bsd_kvm_corefile = filename;
2e0c3539
MK
94 unpush_target (&bsd_kvm_ops);
95 core_kd = temp_kd;
96 push_target (&bsd_kvm_ops);
97
6c613132
PA
98 add_thread_silent (bsd_kvm_ptid);
99 inferior_ptid = bsd_kvm_ptid;
100
594f7785 101 target_fetch_registers (get_current_regcache (), -1);
2e0c3539 102
35f196d9 103 reinit_frame_cache ();
b04f3ab4 104 print_stack_frame (get_selected_frame (NULL), -1, 1);
2e0c3539
MK
105}
106
107static void
108bsd_kvm_close (int quitting)
109{
110 if (core_kd)
111 {
112 if (kvm_close (core_kd) == -1)
8a3fe4f8 113 warning (("%s"), kvm_geterr(core_kd));
2e0c3539
MK
114 core_kd = NULL;
115 }
6c613132
PA
116
117 inferior_ptid = null_ptid;
118 delete_thread_silent (bsd_kvm_ptid);
2e0c3539
MK
119}
120
961cb7b5
MK
121static LONGEST
122bsd_kvm_xfer_memory (CORE_ADDR addr, ULONGEST len,
123 gdb_byte *readbuf, const gdb_byte *writebuf)
2e0c3539 124{
961cb7b5
MK
125 ssize_t nbytes = len;
126
127 if (readbuf)
128 nbytes = kvm_read (core_kd, addr, readbuf, nbytes);
129 if (writebuf && nbytes > 0)
130 nbytes = kvm_write (core_kd, addr, writebuf, nbytes);
131 return nbytes;
132}
2e0c3539 133
961cb7b5
MK
134static LONGEST
135bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
136 const char *annex, gdb_byte *readbuf,
137 const gdb_byte *writebuf,
138 ULONGEST offset, LONGEST len)
139{
140 switch (object)
141 {
142 case TARGET_OBJECT_MEMORY:
143 return bsd_kvm_xfer_memory (offset, len, readbuf, writebuf);
144
145 default:
146 return -1;
147 }
2e0c3539
MK
148}
149
2e5a5020
MK
150static void
151bsd_kvm_files_info (struct target_ops *ops)
152{
153 if (bsd_kvm_corefile && strcmp (bsd_kvm_corefile, _PATH_MEM) != 0)
154 printf_filtered (_("\tUsing the kernel crash dump %s.\n"),
155 bsd_kvm_corefile);
156 else
157 printf_filtered (_("\tUsing the currently running kernel.\n"));
158}
159
2e0c3539
MK
160/* Fetch process control block at address PADDR. */
161
162static int
56be3814 163bsd_kvm_fetch_pcb (struct regcache *regcache, struct pcb *paddr)
2e0c3539
MK
164{
165 struct pcb pcb;
166
167 if (kvm_read (core_kd, (unsigned long) paddr, &pcb, sizeof pcb) == -1)
8a3fe4f8 168 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
169
170 gdb_assert (bsd_kvm_supply_pcb);
56be3814 171 return bsd_kvm_supply_pcb (regcache, &pcb);
2e0c3539
MK
172}
173
174static void
56be3814 175bsd_kvm_fetch_registers (struct regcache *regcache, int regnum)
2e0c3539
MK
176{
177 struct nlist nl[2];
178
179 if (bsd_kvm_paddr)
efe1d7b9 180 {
56be3814 181 bsd_kvm_fetch_pcb (regcache, bsd_kvm_paddr);
efe1d7b9
MK
182 return;
183 }
2e0c3539
MK
184
185 /* On dumping core, BSD kernels store the faulting context (PCB)
186 in the variable "dumppcb". */
187 memset (nl, 0, sizeof nl);
188 nl[0].n_name = "_dumppcb";
189
190 if (kvm_nlist (core_kd, nl) == -1)
8a3fe4f8 191 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
192
193 if (nl[0].n_value != 0)
194 {
195 /* Found dumppcb. If it contains a valid context, return
196 immediately. */
56be3814 197 if (bsd_kvm_fetch_pcb (regcache, (struct pcb *) nl[0].n_value))
2e0c3539
MK
198 return;
199 }
200
201 /* Traditional BSD kernels have a process proc0 that should always
202 be present. The address of proc0's PCB is stored in the variable
203 "proc0paddr". */
204
205 memset (nl, 0, sizeof nl);
206 nl[0].n_name = "_proc0paddr";
207
208 if (kvm_nlist (core_kd, nl) == -1)
8a3fe4f8 209 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
210
211 if (nl[0].n_value != 0)
212 {
213 struct pcb *paddr;
214
215 /* Found proc0paddr. */
216 if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
8a3fe4f8 217 error (("%s"), kvm_geterr (core_kd));
2e0c3539 218
56be3814 219 bsd_kvm_fetch_pcb (regcache, paddr);
2e0c3539
MK
220 return;
221 }
222
223#ifdef HAVE_STRUCT_THREAD_TD_PCB
224 /* In FreeBSD kernels for 5.0-RELEASE and later, the PCB no longer
225 lives in `struct proc' but in `struct thread'. The `struct
226 thread' for the initial thread for proc0 can be found in the
227 variable "thread0". */
228
229 memset (nl, 0, sizeof nl);
230 nl[0].n_name = "_thread0";
231
232 if (kvm_nlist (core_kd, nl) == -1)
8a3fe4f8 233 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
234
235 if (nl[0].n_value != 0)
236 {
237 struct pcb *paddr;
238
239 /* Found thread0. */
efe1d7b9
MK
240 nl[0].n_value += offsetof (struct thread, td_pcb);
241 if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
8a3fe4f8 242 error (("%s"), kvm_geterr (core_kd));
2e0c3539 243
56be3814 244 bsd_kvm_fetch_pcb (regcache, paddr);
2e0c3539
MK
245 return;
246 }
247#endif
248
3d263c1d
BI
249 /* i18n: PCB == "Process Control Block" */
250 error (_("Cannot find a valid PCB"));
2e0c3539
MK
251}
252\f
253
963c4174 254/* Kernel memory interface commands. */
fdb1bf9d 255struct cmd_list_element *bsd_kvm_cmdlist;
963c4174
MK
256
257static void
258bsd_kvm_cmd (char *arg, int fromtty)
259{
260 /* ??? Should this become an alias for "target kvm"? */
261}
262
263#ifndef HAVE_STRUCT_THREAD_TD_PCB
264
265static void
266bsd_kvm_proc_cmd (char *arg, int fromtty)
267{
268 CORE_ADDR addr;
269
270 if (arg == NULL)
3d263c1d 271 error_no_arg (_("proc address"));
963c4174
MK
272
273 if (core_kd == NULL)
3d263c1d 274 error (_("No kernel memory image."));
963c4174
MK
275
276 addr = parse_and_eval_address (arg);
da7d81e3
NW
277#ifdef HAVE_STRUCT_LWP
278 addr += offsetof (struct lwp, l_addr);
279#else
963c4174 280 addr += offsetof (struct proc, p_addr);
da7d81e3 281#endif
963c4174
MK
282
283 if (kvm_read (core_kd, addr, &bsd_kvm_paddr, sizeof bsd_kvm_paddr) == -1)
8a3fe4f8 284 error (("%s"), kvm_geterr (core_kd));
963c4174 285
594f7785 286 target_fetch_registers (get_current_regcache (), -1);
963c4174 287
35f196d9 288 reinit_frame_cache ();
b04f3ab4 289 print_stack_frame (get_selected_frame (NULL), -1, 1);
963c4174
MK
290}
291
292#endif
293
294static void
295bsd_kvm_pcb_cmd (char *arg, int fromtty)
296{
297 if (arg == NULL)
3d263c1d
BI
298 /* i18n: PCB == "Process Control Block" */
299 error_no_arg (_("pcb address"));
963c4174
MK
300
301 if (core_kd == NULL)
3d263c1d 302 error (_("No kernel memory image."));
963c4174 303
57ac95b8 304 bsd_kvm_paddr = (struct pcb *)(u_long) parse_and_eval_address (arg);
963c4174 305
594f7785 306 target_fetch_registers (get_current_regcache (), -1);
963c4174 307
35f196d9 308 reinit_frame_cache ();
b04f3ab4 309 print_stack_frame (get_selected_frame (NULL), -1, 1);
963c4174
MK
310}
311
6c613132
PA
312static int
313bsd_kvm_thread_alive (ptid_t ptid)
314{
315 return 1;
316}
317
318static char *
117de6a9 319bsd_kvm_pid_to_str (struct target_ops *ops, ptid_t ptid)
6c613132
PA
320{
321 static char buf[64];
322 xsnprintf (buf, sizeof buf, "<kvm>");
323 return buf;
324}
325
2e0c3539
MK
326/* Add the libkvm interface to the list of all possible targets and
327 register CUPPLY_PCB as the architecture-specific process control
328 block interpreter. */
329
330void
331bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
332{
333 gdb_assert (bsd_kvm_supply_pcb == NULL);
334 bsd_kvm_supply_pcb = supply_pcb;
335
336 bsd_kvm_ops.to_shortname = "kvm";
3d263c1d
BI
337 bsd_kvm_ops.to_longname = _("Kernel memory interface");
338 bsd_kvm_ops.to_doc = _("Use a kernel virtual memory image as a target.\n\
339Optionally specify the filename of a core dump.");
2e0c3539
MK
340 bsd_kvm_ops.to_open = bsd_kvm_open;
341 bsd_kvm_ops.to_close = bsd_kvm_close;
342 bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers;
961cb7b5 343 bsd_kvm_ops.to_xfer_partial = bsd_kvm_xfer_partial;
2e5a5020 344 bsd_kvm_ops.to_files_info = bsd_kvm_files_info;
6c613132
PA
345 bsd_kvm_ops.to_thread_alive = bsd_kvm_thread_alive;
346 bsd_kvm_ops.to_pid_to_str = bsd_kvm_pid_to_str;
2e0c3539
MK
347 bsd_kvm_ops.to_stratum = process_stratum;
348 bsd_kvm_ops.to_has_memory = 1;
349 bsd_kvm_ops.to_has_stack = 1;
350 bsd_kvm_ops.to_has_registers = 1;
351 bsd_kvm_ops.to_magic = OPS_MAGIC;
352
353 add_target (&bsd_kvm_ops);
963c4174 354
3d263c1d
BI
355 add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\
356Generic command for manipulating the kernel memory interface."),
963c4174
MK
357 &bsd_kvm_cmdlist, "kvm ", 0, &cmdlist);
358
359#ifndef HAVE_STRUCT_THREAD_TD_PCB
360 add_cmd ("proc", class_obscure, bsd_kvm_proc_cmd,
3d263c1d 361 _("Set current context from proc address"), &bsd_kvm_cmdlist);
963c4174
MK
362#endif
363 add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
3d263c1d
BI
364 /* i18n: PCB == "Process Control Block" */
365 _("Set current context from pcb address"), &bsd_kvm_cmdlist);
6c613132
PA
366
367 /* Some notes on the ptid usage on this target.
368
369 The pid field represents the kvm inferior instance. Currently,
370 we don't support multiple kvm inferiors, but we start at 1
371 anyway. The lwp field is set to != 0, in case the core wants to
372 refer to the whole kvm inferior with ptid(1,0,0).
373
374 If kvm is made to export running processes as gdb threads,
375 the following form can be used:
376 ptid (1, 1, 0) -> kvm inferior 1, in kernel
377 ptid (1, 1, 1) -> kvm inferior 1, process 1
378 ptid (1, 1, 2) -> kvm inferior 1, process 2
379 ptid (1, 1, n) -> kvm inferior 1, process n
380 */
381 bsd_kvm_ptid = ptid_build (1, 1, 0);
2e0c3539 382}
This page took 0.277828 seconds and 4 git commands to generate.