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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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