]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/bsd-kvm.c
* target.h (struct target_ops): Make to_has_all_memory,
[thirdparty/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
28439f5e
PA
175bsd_kvm_fetch_registers (struct target_ops *ops,
176 struct regcache *regcache, int regnum)
2e0c3539
MK
177{
178 struct nlist nl[2];
179
180 if (bsd_kvm_paddr)
efe1d7b9 181 {
56be3814 182 bsd_kvm_fetch_pcb (regcache, bsd_kvm_paddr);
efe1d7b9
MK
183 return;
184 }
2e0c3539
MK
185
186 /* On dumping core, BSD kernels store the faulting context (PCB)
187 in the variable "dumppcb". */
188 memset (nl, 0, sizeof nl);
189 nl[0].n_name = "_dumppcb";
190
191 if (kvm_nlist (core_kd, nl) == -1)
8a3fe4f8 192 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
193
194 if (nl[0].n_value != 0)
195 {
196 /* Found dumppcb. If it contains a valid context, return
197 immediately. */
56be3814 198 if (bsd_kvm_fetch_pcb (regcache, (struct pcb *) nl[0].n_value))
2e0c3539
MK
199 return;
200 }
201
202 /* Traditional BSD kernels have a process proc0 that should always
203 be present. The address of proc0's PCB is stored in the variable
204 "proc0paddr". */
205
206 memset (nl, 0, sizeof nl);
207 nl[0].n_name = "_proc0paddr";
208
209 if (kvm_nlist (core_kd, nl) == -1)
8a3fe4f8 210 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
211
212 if (nl[0].n_value != 0)
213 {
214 struct pcb *paddr;
215
216 /* Found proc0paddr. */
217 if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
8a3fe4f8 218 error (("%s"), kvm_geterr (core_kd));
2e0c3539 219
56be3814 220 bsd_kvm_fetch_pcb (regcache, paddr);
2e0c3539
MK
221 return;
222 }
223
224#ifdef HAVE_STRUCT_THREAD_TD_PCB
225 /* In FreeBSD kernels for 5.0-RELEASE and later, the PCB no longer
226 lives in `struct proc' but in `struct thread'. The `struct
227 thread' for the initial thread for proc0 can be found in the
228 variable "thread0". */
229
230 memset (nl, 0, sizeof nl);
231 nl[0].n_name = "_thread0";
232
233 if (kvm_nlist (core_kd, nl) == -1)
8a3fe4f8 234 error (("%s"), kvm_geterr (core_kd));
2e0c3539
MK
235
236 if (nl[0].n_value != 0)
237 {
238 struct pcb *paddr;
239
240 /* Found thread0. */
efe1d7b9
MK
241 nl[0].n_value += offsetof (struct thread, td_pcb);
242 if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
8a3fe4f8 243 error (("%s"), kvm_geterr (core_kd));
2e0c3539 244
56be3814 245 bsd_kvm_fetch_pcb (regcache, paddr);
2e0c3539
MK
246 return;
247 }
248#endif
249
3d263c1d
BI
250 /* i18n: PCB == "Process Control Block" */
251 error (_("Cannot find a valid PCB"));
2e0c3539
MK
252}
253\f
254
963c4174 255/* Kernel memory interface commands. */
fdb1bf9d 256struct cmd_list_element *bsd_kvm_cmdlist;
963c4174
MK
257
258static void
259bsd_kvm_cmd (char *arg, int fromtty)
260{
261 /* ??? Should this become an alias for "target kvm"? */
262}
263
264#ifndef HAVE_STRUCT_THREAD_TD_PCB
265
266static void
267bsd_kvm_proc_cmd (char *arg, int fromtty)
268{
269 CORE_ADDR addr;
270
271 if (arg == NULL)
3d263c1d 272 error_no_arg (_("proc address"));
963c4174
MK
273
274 if (core_kd == NULL)
3d263c1d 275 error (_("No kernel memory image."));
963c4174
MK
276
277 addr = parse_and_eval_address (arg);
da7d81e3
NW
278#ifdef HAVE_STRUCT_LWP
279 addr += offsetof (struct lwp, l_addr);
280#else
963c4174 281 addr += offsetof (struct proc, p_addr);
da7d81e3 282#endif
963c4174
MK
283
284 if (kvm_read (core_kd, addr, &bsd_kvm_paddr, sizeof bsd_kvm_paddr) == -1)
8a3fe4f8 285 error (("%s"), kvm_geterr (core_kd));
963c4174 286
594f7785 287 target_fetch_registers (get_current_regcache (), -1);
963c4174 288
35f196d9 289 reinit_frame_cache ();
b04f3ab4 290 print_stack_frame (get_selected_frame (NULL), -1, 1);
963c4174
MK
291}
292
293#endif
294
295static void
296bsd_kvm_pcb_cmd (char *arg, int fromtty)
297{
298 if (arg == NULL)
3d263c1d
BI
299 /* i18n: PCB == "Process Control Block" */
300 error_no_arg (_("pcb address"));
963c4174
MK
301
302 if (core_kd == NULL)
3d263c1d 303 error (_("No kernel memory image."));
963c4174 304
57ac95b8 305 bsd_kvm_paddr = (struct pcb *)(u_long) parse_and_eval_address (arg);
963c4174 306
594f7785 307 target_fetch_registers (get_current_regcache (), -1);
963c4174 308
35f196d9 309 reinit_frame_cache ();
b04f3ab4 310 print_stack_frame (get_selected_frame (NULL), -1, 1);
963c4174
MK
311}
312
6c613132 313static int
28439f5e
PA
314bsd_kvm_thread_alive (struct target_ops *ops,
315 ptid_t ptid)
6c613132
PA
316{
317 return 1;
318}
319
320static char *
117de6a9 321bsd_kvm_pid_to_str (struct target_ops *ops, ptid_t ptid)
6c613132
PA
322{
323 static char buf[64];
324 xsnprintf (buf, sizeof buf, "<kvm>");
325 return buf;
326}
327
c35b1492
PA
328static int
329bsd_kvm_return_one (struct target_ops *ops)
330{
331 return 1;
332}
333
2e0c3539
MK
334/* Add the libkvm interface to the list of all possible targets and
335 register CUPPLY_PCB as the architecture-specific process control
336 block interpreter. */
337
338void
339bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
340{
341 gdb_assert (bsd_kvm_supply_pcb == NULL);
342 bsd_kvm_supply_pcb = supply_pcb;
343
344 bsd_kvm_ops.to_shortname = "kvm";
3d263c1d
BI
345 bsd_kvm_ops.to_longname = _("Kernel memory interface");
346 bsd_kvm_ops.to_doc = _("Use a kernel virtual memory image as a target.\n\
347Optionally specify the filename of a core dump.");
2e0c3539
MK
348 bsd_kvm_ops.to_open = bsd_kvm_open;
349 bsd_kvm_ops.to_close = bsd_kvm_close;
350 bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers;
961cb7b5 351 bsd_kvm_ops.to_xfer_partial = bsd_kvm_xfer_partial;
2e5a5020 352 bsd_kvm_ops.to_files_info = bsd_kvm_files_info;
6c613132
PA
353 bsd_kvm_ops.to_thread_alive = bsd_kvm_thread_alive;
354 bsd_kvm_ops.to_pid_to_str = bsd_kvm_pid_to_str;
2e0c3539 355 bsd_kvm_ops.to_stratum = process_stratum;
c35b1492
PA
356 bsd_kvm_ops.to_has_memory = bsd_kvm_return_one;
357 bsd_kvm_ops.to_has_stack = bsd_kvm_return_one;
358 bsd_kvm_ops.to_has_registers = bsd_kvm_return_one;
2e0c3539
MK
359 bsd_kvm_ops.to_magic = OPS_MAGIC;
360
361 add_target (&bsd_kvm_ops);
963c4174 362
3d263c1d
BI
363 add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\
364Generic command for manipulating the kernel memory interface."),
963c4174
MK
365 &bsd_kvm_cmdlist, "kvm ", 0, &cmdlist);
366
367#ifndef HAVE_STRUCT_THREAD_TD_PCB
368 add_cmd ("proc", class_obscure, bsd_kvm_proc_cmd,
3d263c1d 369 _("Set current context from proc address"), &bsd_kvm_cmdlist);
963c4174
MK
370#endif
371 add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
3d263c1d
BI
372 /* i18n: PCB == "Process Control Block" */
373 _("Set current context from pcb address"), &bsd_kvm_cmdlist);
6c613132
PA
374
375 /* Some notes on the ptid usage on this target.
376
377 The pid field represents the kvm inferior instance. Currently,
378 we don't support multiple kvm inferiors, but we start at 1
379 anyway. The lwp field is set to != 0, in case the core wants to
380 refer to the whole kvm inferior with ptid(1,0,0).
381
382 If kvm is made to export running processes as gdb threads,
383 the following form can be used:
384 ptid (1, 1, 0) -> kvm inferior 1, in kernel
385 ptid (1, 1, 1) -> kvm inferior 1, process 1
386 ptid (1, 1, 2) -> kvm inferior 1, process 2
387 ptid (1, 1, n) -> kvm inferior 1, process n
388 */
389 bsd_kvm_ptid = ptid_build (1, 1, 0);
2e0c3539 390}