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