OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [bsd-kvm.c] - Blame information for rev 868

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* BSD Kernel Data Access Library (libkvm) interface.
2
 
3
   Copyright (C) 2004, 2005, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
#include "cli/cli-cmds.h"
22
#include "command.h"
23
#include "frame.h"
24
#include "regcache.h"
25
#include "target.h"
26
#include "value.h"
27
#include "gdbcore.h"            /* for get_exec_file */
28
 
29
#include "gdb_assert.h"
30
#include <fcntl.h>
31
#include <kvm.h>
32
#ifdef HAVE_NLIST_H
33
#include <nlist.h>
34
#endif
35
#include <paths.h>
36
#include "readline/readline.h"
37
#include <sys/param.h>
38
#include <sys/proc.h>
39
#include <sys/user.h>
40
 
41
#include "bsd-kvm.h"
42
 
43
/* Kernel memory device file.  */
44
static const char *bsd_kvm_corefile;
45
 
46
/* Kernel memory interface descriptor.  */
47
static kvm_t *core_kd;
48
 
49
/* Address of process control block.  */
50
static struct pcb *bsd_kvm_paddr;
51
 
52
/* Pointer to architecture-specific function that reconstructs the
53
   register state from PCB and supplies it to REGCACHE.  */
54
static int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb);
55
 
56
/* Target ops for libkvm interface.  */
57
static struct target_ops bsd_kvm_ops;
58
 
59
static void
60
bsd_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
        {
75
          temp = concat (current_directory, "/", filename, (char *)NULL);
76
          xfree (filename);
77
          filename = temp;
78
        }
79
    }
80
 
81
  execfile = get_exec_file (0);
82
  temp_kd = kvm_openfiles (execfile, filename, NULL,
83
                           write_files ? O_RDWR : O_RDONLY, errbuf);
84
  if (temp_kd == NULL)
85
    error (("%s"), errbuf);
86
 
87
  bsd_kvm_corefile = filename;
88
  unpush_target (&bsd_kvm_ops);
89
  core_kd = temp_kd;
90
  push_target (&bsd_kvm_ops);
91
 
92
  target_fetch_registers (get_current_regcache (), -1);
93
 
94
  reinit_frame_cache ();
95
  print_stack_frame (get_selected_frame (NULL), -1, 1);
96
}
97
 
98
static void
99
bsd_kvm_close (int quitting)
100
{
101
  if (core_kd)
102
    {
103
      if (kvm_close (core_kd) == -1)
104
        warning (("%s"), kvm_geterr(core_kd));
105
      core_kd = NULL;
106
    }
107
}
108
 
109
static LONGEST
110
bsd_kvm_xfer_memory (CORE_ADDR addr, ULONGEST len,
111
                     gdb_byte *readbuf, const gdb_byte *writebuf)
112
{
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
}
121
 
122
static LONGEST
123
bsd_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
    }
136
}
137
 
138
static void
139
bsd_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
 
148
/* Fetch process control block at address PADDR.  */
149
 
150
static int
151
bsd_kvm_fetch_pcb (struct regcache *regcache, struct pcb *paddr)
152
{
153
  struct pcb pcb;
154
 
155
  if (kvm_read (core_kd, (unsigned long) paddr, &pcb, sizeof pcb) == -1)
156
    error (("%s"), kvm_geterr (core_kd));
157
 
158
  gdb_assert (bsd_kvm_supply_pcb);
159
  return bsd_kvm_supply_pcb (regcache, &pcb);
160
}
161
 
162
static void
163
bsd_kvm_fetch_registers (struct regcache *regcache, int regnum)
164
{
165
  struct nlist nl[2];
166
 
167
  if (bsd_kvm_paddr)
168
    {
169
      bsd_kvm_fetch_pcb (regcache, bsd_kvm_paddr);
170
      return;
171
    }
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)
179
    error (("%s"), kvm_geterr (core_kd));
180
 
181
  if (nl[0].n_value != 0)
182
    {
183
      /* Found dumppcb. If it contains a valid context, return
184
         immediately.  */
185
      if (bsd_kvm_fetch_pcb (regcache, (struct pcb *) nl[0].n_value))
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)
197
    error (("%s"), kvm_geterr (core_kd));
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)
205
        error (("%s"), kvm_geterr (core_kd));
206
 
207
      bsd_kvm_fetch_pcb (regcache, paddr);
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)
221
    error (("%s"), kvm_geterr (core_kd));
222
 
223
  if (nl[0].n_value != 0)
224
    {
225
      struct pcb *paddr;
226
 
227
      /* Found thread0.  */
228
      nl[0].n_value += offsetof (struct thread, td_pcb);
229
      if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
230
        error (("%s"), kvm_geterr (core_kd));
231
 
232
      bsd_kvm_fetch_pcb (regcache, paddr);
233
      return;
234
    }
235
#endif
236
 
237
  /* i18n: PCB == "Process Control Block" */
238
  error (_("Cannot find a valid PCB"));
239
}
240
 
241
 
242
/* Kernel memory interface commands.  */
243
struct cmd_list_element *bsd_kvm_cmdlist;
244
 
245
static void
246
bsd_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
 
253
static void
254
bsd_kvm_proc_cmd (char *arg, int fromtty)
255
{
256
  CORE_ADDR addr;
257
 
258
  if (arg == NULL)
259
    error_no_arg (_("proc address"));
260
 
261
  if (core_kd == NULL)
262
    error (_("No kernel memory image."));
263
 
264
  addr = parse_and_eval_address (arg);
265
#ifdef HAVE_STRUCT_LWP
266
  addr += offsetof (struct lwp, l_addr);
267
#else
268
  addr += offsetof (struct proc, p_addr);
269
#endif
270
 
271
  if (kvm_read (core_kd, addr, &bsd_kvm_paddr, sizeof bsd_kvm_paddr) == -1)
272
    error (("%s"), kvm_geterr (core_kd));
273
 
274
  target_fetch_registers (get_current_regcache (), -1);
275
 
276
  reinit_frame_cache ();
277
  print_stack_frame (get_selected_frame (NULL), -1, 1);
278
}
279
 
280
#endif
281
 
282
static void
283
bsd_kvm_pcb_cmd (char *arg, int fromtty)
284
{
285
  if (arg == NULL)
286
    /* i18n: PCB == "Process Control Block" */
287
    error_no_arg (_("pcb address"));
288
 
289
  if (core_kd == NULL)
290
    error (_("No kernel memory image."));
291
 
292
  bsd_kvm_paddr = (struct pcb *)(u_long) parse_and_eval_address (arg);
293
 
294
  target_fetch_registers (get_current_regcache (), -1);
295
 
296
  reinit_frame_cache ();
297
  print_stack_frame (get_selected_frame (NULL), -1, 1);
298
}
299
 
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
 
304
void
305
bsd_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";
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\
313
Optionally specify the filename of a core dump.");
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;
317
  bsd_kvm_ops.to_xfer_partial = bsd_kvm_xfer_partial;
318
  bsd_kvm_ops.to_files_info = bsd_kvm_files_info;
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);
326
 
327
  add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\
328
Generic command for manipulating the kernel memory interface."),
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,
333
           _("Set current context from proc address"), &bsd_kvm_cmdlist);
334
#endif
335
  add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
336
           /* i18n: PCB == "Process Control Block" */
337
           _("Set current context from pcb address"), &bsd_kvm_cmdlist);
338
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.